再利用可能性のためのインデックス変換/マッピングに名前を生成してコンパイルする

StackOverflow https://stackoverflow.com//questions/11665503

  •  11-12-2019
  •  | 
  •  

質問

サービスからデータを取得したとします(コントロールできない)

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> の列名は、My Dataクラスのプロパティとして表されるになることができるEntityにマッピング/変換したいと思います。私はになるかもしれませんが、サービスによって返されたすべてのデータが必要ではなく、それのほんの一部が必要なので

変換

これは翻訳をするためのアルゴリズムの抽象化です:

  1. IDictionary<string, int>ColumnNamesを作成するので、個々の列名を個々の行の配列インデックスに簡単にマッピングできます。
  2. Reflectionを使用してMy Entityプロパティの名前を調べて、列名と一致することができるように
  3. Data.Rowsを繰り返し、Entityオブジェクトを作成し、#1で行われたマッピングに従ってプロパティを入力します。それらを設定するためにプロパティに反射とSetValueを使用する可能性があります。

    最適化

    上位アルゴリズムはもちろん作業であるが、それが反映を使用するのでそれがいくつかのキャッシングをするべきであること、そしておそらくその場である可能性があるので、それはかなりのものをスピードアップすることができると思います。

    ステップ1と2が完了したら、実際に文字列の配列をとり、インデックスを直接インデックスを使用してインスタンス化し、をコンパイルし、をキャッシュする方法を将来の再利用のためにインスタンス化することができます。

    通常、結果のページを取得するので、後続の要求は同じコンパイル方法を再利用します。

    追加の事実

    これは質問(および回答)に不可欠ではありませんが、これらが名前で一致しない場合の列からプロパティのマッピングに役立つ2つの属性を作成しました。私は最も明白なMapNameAttribute(文字列を取り、オプションでオプションで任意選択でも有効にし、oppentivityを有効にします)およびIgnoreMappingAttributeのPropertiesのデータにマッピングされるべきではありません。しかし、これらの属性は上限アルゴリズムの手順2で読み込まれているため、プロパティ名は収集され、この宣言型メタデータに従って列名と一致するように変更されます。

    質問

    そのような方法を生成してコンパイルするための最善かつ最も簡単な方法は何ですか?ラムダ表現? Entityクラス?

    生成されたコードとコンパイル済みのコードの例が似ていますか。私はマッピングがかなり一般的なシナリオです。

    :その間、私はPetapoco(そしてまた大量)を調べるでしょう(そして、彼らが両方ともマッピング目的のために正確に編集とキャッシングをしているので、Petapoco(多分大量)を調べます。

役に立ちましたか?

解決

提案: Nuget からFastMemberを入手する

それからだけ使用してください:

var accessor = TypeAccessor.Create(typeof(Entity));
.

現在の反復のmemberNamenewValueを見つけたら、

accessor[obj, memberName] = newValue;
.

これはあなたが尋ねていることをするように設計されています。内部的には、前に見た場合は一連の種類を維持します。新しいタイプが表示されている場合は、TypeAccessorの新しいサブクラス(TypeBuilderを介して)作成してキャッシュします。それぞれの固有のTypeAccessorは、そのタイプのプロパティを認識しており、基本的にはa:のように機能します。

switch(memberName) {
    case "Foo": obj.Foo = (int)newValue;
    case "Bar": obj.Bar = (string)newValue;
    // etc
}
.

これはキャッシュされているので、あなたは初めてあなたのタイプを見たことがあるのは初めての費用(実際には big>コストではありません)のみを支払うだけです。残りの時間は無料です。 ILGenerator を直接使用するため、例えばExpressionまたはCodeDOMを介して不要な抽象化も回避されますので、それができる限り速いです。

(私はdynamic型の場合、IDynamicMetaObjectProviderを実装するタイプも明確にする必要があります。


追加:

を使っていることは次のとおりです。その後、すべてのVoodooがメンバー名ではなく、 data 名で起こります。

これは線を変えることを意味するでしょう:

il.Emit(OpCodes.Ldstr, prop.Name);
.

il.Emit(OpCodes.Ldstr, field.Name);
.

FastMemberMapNameAttributeの両方で、IgnoreMappingAttributeループの開始時にWriteGetterを実行する場合は、無視される場合は

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top