次のように(制御できない)サービスからデータを取得するとします。
public class Data
{
// an array of column names
public string[] ColumnNames { get; set; }
// an array of rows that contain arrays of strings as column values
public string[][] Rows { get; get; }
}
IEnumerable<Entity>
中間層では、これを、の列名がクラスのプロパティとして表されるData
場所にマップ/変換したいと思いEntity
ます。サービスから返されるすべてのデータではなく、一部のデータが必要な場合があるため、私はそう言いました。
変身
これは、変換を行うアルゴリズムの抽象化です。
- を作成して、
IDictionary<string, int>
個々ColumnNames
の列名を個々の行の配列インデックスに簡単にマップできるようにします。 Entity
リフレクションを使用してプロパティの名前を調べ、列名と照合できるようにします- #1で行ったマッピングに従って、オブジェクトを繰り返し
Data.Rows
作成し、プロパティにデータを入力します。Entity
リフレクションとSetValue
オンプロパティを使用してそれらを設定する可能性があります。
最適化
上位のアルゴリズムはもちろん機能しますが、リフレクションを使用するため、キャッシュを実行し、場合によってはオンザフライのコンパイルを実行する必要があります。これにより、処理速度が大幅に向上する可能性があります。
手順1と2が完了すると、文字列の配列を取得し、インデックスを使用してエンティティを直接インスタンス化し、コンパイルして将来の再利用のためにキャッシュするメソッドを実際に生成できます。
私は通常、結果のページを取得しているので、後続のリクエストは同じコンパイル済みメソッドを再利用します。
追加の事実
これは質問(および回答)に必須ではありませんが、名前が一致しない場合に列からプロパティへのマッピングに役立つ2つの属性も作成しました。私は最も明白なものMapNameAttribute
(文字列を取り、オプションで大文字と小文字の区別も有効にする)を作成し、データにマップされるべきではないIgnoreMappingAttribute
プロパティを作成しました。Entity
ただし、これらの属性は上位アルゴリズムのステップ2で読み取られるため、プロパティ名が収集され、この宣言型メタデータに従って名前が変更され、列名と一致します。
質問
そのようなメソッドを生成してコンパイルするための最良かつ最も簡単な方法は何ですか?ラムダ式?CSharpCodeProvider
クラス?
同様のことを行う、生成およびコンパイルされたコードの例はありますか?マッピングはかなり一般的なシナリオだと思います。
注:それまでの間、PetaPoco(およびおそらくMassive)についても検討します。これは、どちらもマッピングの目的で正確にオンザフライでコンパイルとキャッシュを実行するためです。