2009-08-12 13 views
0

私はエンタープライズデータ(さまざまなデータベース/テーブルから)を、特定の形式のフラットファイルに変換してレガシーアプリケーションで使用する必要があります。フラットファイル変換のデータモデルを設計する...デリゲートまたは継承?

public class StatusCode 
{ 
    public String Id { get; set; } 
    public Char Level { get; set; } 
    public String Description { get; set; } 
} 

データソースからこれらのレコードの一部またはすべてを選択します。そして、各エンティティをファイルの1行にマップする必要があります。データの調整(パディング、変形、または処理null)が必要な場合があります。

public delegate String MapEntity<T>(T entity); 
public MapEntity<StatusCode> MapStatusCode = delegate(StatusCode entity) 
{ 
    return String.Format("{0},{1},{2}", 
     entity.Id.PadLeft(3, '0'), 
     entity.Level == 'S' ? 0 : 1, 
     entity.Description ?? "-"); 
} 

問題は、どのように変換クラスを記述しますか?マッピングデリゲートをとる「DefaultFileCreator」を提供していますか?

public interface IFileCreator 
{ 
    Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities); 
} 

public class DefaultFileCreator : IFileCreator 
{ 
    public Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (T entity in entities) 
      sb.AppendLine(map(entity)); 

     return Encoding.Default.GetBytes(sb.ToString()); 
    } 
} 

... 
fileCreator.Create(MapStatusCode, repository<StatusCode>.FindAll()); 
... 

このソリューションでは、マッピングの代理人をどこでどの範囲で保持する必要があるか心配です。そして、どうすれば私はT(私がこれまで必要だったか)を知らずにそれらを呼び出すつもりです。

または、インタフェースを変更して具体的なクラスでマッピングする必要がありますか?

public interface IFileCreator<T> 
{ 
    Byte[] Create(IEnumerable<T> entities); 
} 

public abstract class FileCreator : IFileCreator<T> 
{ 
    protected abstract String Map(T entity); 

    public Byte[] Create(IEnumerable<T> entities) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (T entity in entities) 
      sb.AppendLine(Map(entity)); 

     return Encoding.Default.GetBytes(sb.ToString()); 
    } 
} 

public class StatusCodeFile : FileCreator<StatusCode> 
{ 
    public override String Map(T entity) 
    { 
     return String.Format("{0},{1},{2}", 
      entity.Id.PadLeft(3, '0'), 
      entity.Level == 'S' ? 0 : 1, 
      entity.Description ?? "-"); 
    } 
} 

このソリューションは、具象クラスで爆発しますが、マッピング代理者ほど薄いです。そして、私はIFileCreator<T>と工場で働いているほうが快適だと感じています。 (再び必要な場合のみ)。

StringBuilderループとByte[]エンコーディングが単純なので、基本クラスが有用であると仮定しています。具体的なクラスは、抽象メソッドを呼び出すのではなく、基本クラスのデリゲートプロパティを設定する必要がありますか?メソッドにtypeパラメータを保持する必要があります(また、それがベース/コンクリートクラスにどのような影響を与えますか)。

私はどんな解決策でもあります。私の主な目標はメンテナンスの容易さです。私は現在12のモデル/ファイルを持っていますが、これは21まで増加する可能性があります。任意のヘッダー/フッター行を任意のファイルに挿入する必要があるかもしれません(なぜ、私はオーバーライド可能な基本クラスメソッドMapが好きです)。

答えて

0

私は変換のいくつかを書いたので、私はクラスごとのアプローチに傾いています。私は、ファイルが適切に構築されていることを確認するために、偽のモデルに対して単体テストを実行することができなければなりません。

私はマッピング - デリゲートを、それらが属している "ワークフロー"クラス(モデル/ファイルごとに1つの "ワークフロー")に対してプライベートにしています。単体テストに公開するか、中間ファイルコンテンツを出力する必要があります(ワークフローは完成したファイルをデータストアに保存します)。

クラスあたりのマッピングは、より多くのテスト可能で分解可能なようです。

+0

また、各具体的なクラスMapEntity(デリゲート)の抽象プロパティをオーバーライドすることも検討しています。メソッドMap(T)をオーバーライドするのと同じ効果があります。異なった外観。 –

1

可能なマッピングごとに具体的なサブクラスを実際に作成する必要がありますか?おそらく、XMLファイル(またはデータベース)を使用して、各種類のファイルの形式/内容を記述することは可能でしょう。次に、「FileType」キーを受け取り、XMLからの書式設定情報を使用してそのFileTypeのファイルを構築する方法を決定する単一のクラスがあります。

+0

これは、マッピングデリゲートを使用するのと同じ解決策(インテントで)だと思います。 –

+0

@ajmastrean - 私はそれをより詳細に見るので、あなたは正しいです。 "T"が何であるか知らずにこれを行う方法については、すべてのプロパティを取得するためにリフレクションを使うだけなので、とにかくオブジェクトのタイプを実際に知る必要はありません。 –

関連する問題