2017-10-15 3 views
0

インスタンスコンストラクタでRTで動的に作成したバッキングフィールドを持つプロパティを割り当てる方法の解決方法をお探しください。このシグネチャは、自動プロパティとしてのコンパイラ生成属性と一致します。基本的には、以下に示すコードと同等です。Reflection Emitでコンストラクタのフィールドを割り当てる

.NETコア2.0

質問を使用する:どのように私はエミットを使用して、コンストラクタ内のバッキングフィールドを割り当てていますか?

例えば

:インタフェース内で定義された方法に比べて

public class MyClass { 
    public MyClass(int f1, string f2) { 
    _field1 = f1; 
    _field2 = f2; 
    } 

    private readonly int _field1; 
    private readonly string _field2; 

    public int Field1 { get; } 
    public string Field2 { get; } 
} 

private static void CreateConstructor(TypeBuilder typeBuilder, IReadOnlyList<dynamic> backingFields) { 
    var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] {typeof(KeyValuePair<string, string>), typeof(Dictionary<string, Type>)}); 
    var ctorIL = constructorBuilder.GetILGenerator(); 

    // Load the current instance ref in arg 0, along 
    // with the value of parameter "x" stored in arg X, into stfld. 

    for (var x = 0; x < backingFields.Count; x++) { 
    ctorIL.Emit(OpCodes.Ldarg_0); 
    ctorIL.Emit(OpCodes.Ldarg_S, x+1); 
    ctorIL.Emit(OpCodes.Stfld, backingFields[x]); 
    } 

    ctorIL.Emit(OpCodes.Ret); 
} 

public .cctor(KeyValuePair<string, string> kvp, Dictionary<string, Type> collection) { 
    _Name = kvp.Key; 
    _JSON = kvp.Value; 
    _PropertyInfo = collection; 
    } 

反復し、新しいタイプの新しいプロパティをプライベートセッター/ W &アクセサを作成します。

public interface IComplexType { 
    string Name { get; set; } 
    string JSON { get; set; } 
    object PropertyInfo { get; set; } 
    } 
+0

をコードDOMを大幅にありRefectionよりも簡単Emmit – MickyD

+1

投稿したコードは、バッキングフィールドにコンストラクタ引数を割り当てるようです。それは働いていないのですか? –

+0

何かが正しく動作していません。型をコンパイルして返します。インスタンスを作成することができます。検査すると、いくつかのフィールドやプロパティが欠落しています。たとえば、3つのフィールドを含むInterfaceを持つクラスが必要です。 JSONは動作するクラスに追加のフィールド/プロパティ/メソッドを追加しますが、メンバーをインターフェイスで読み取り専用にするようにしています。 パブリックインターフェイスIComplexType { string Name {get;セット; } string JSON {get;セット; } [バインド可能(true)] [TypeConverter(typeof(StringConverter))]オブジェクトPropertyInfo {get;セット; } } – Latency

答えて

1

解決済み!

Ldarg_1がKeyValuePairとして難しく、キー&の値をそれぞれ割り当てているため、コンストラクタ引数を反復回数に合わせて変更する必要がありました。次のようにコンストラクタが定義されているKVPを排除し、追加のパラメータを提供することにより

var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] {typeof(string), typeof(string), typeof(Dictionary<string, Type>)}); 
    var ctorIl = constructorBuilder.GetILGenerator(); 

    for (var x = 0; x < backingFields.Count; x++) { 
    ctorIl.Emit(OpCodes.Ldarg_0); 
    ctorIl.Emit(OpCodes.Ldarg_S, x + 1); 
    ctorIl.Emit(OpCodes.Stfld, backingFields[x]); 
    } 

    ctorIl.Emit(OpCodes.Ret); 

起動するには、私はちょうどここKVPの内容を抽出:

return (T) Activator.CreateInstance(TypeCollection[type], kvp.Key, kvp.Value, collection); 
関連する問題