2017-10-15 1 views
0

Auf der Suche nach Auflösung, wie Eigenschaften mit Sicherungsfeldern zuweisen, die ich dynamisch bei RT in einem Instanzkonstruktor erstellt habe. Die Signaturen stimmen mit vom Compiler erzeugten Attributen als Auto-Eigenschaften überein. Im Wesentlichen entsprechen sie dem unten aufgeführten Code.Felder im Konstruktor über Reflection zuweisen Emittieren

Mit .NET Core 2.0

Frage: Wie ordne ich die Unterstützung von Feldern im Konstruktor Emit?

Zum Beispiel:

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; 
    } 

Iterate über Methoden innerhalb Schnittstelle definiert und eine neue Eigenschaften & Accessoren w/private Einrichtungen für die Festlegung der neuen Art erstellen .

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

-Code DOM signifikant ist einfacher als Refection Emit – MickyD

+1

Der Code, den Sie gepostet haben, scheint die Konstruktorargumente den Hintergrundfeldern zuzuweisen. Funktioniert es nicht? –

+0

Etwas funktioniert nicht richtig. Es kompiliert und gibt den Typ zurück. Kann eine Instanz erstellen .. wenn ich überprüft werde, fehlen mir einige Felder/Eigenschaften. Zum Beispiel soll ich eine Klasse mit Interface haben, die 3 Felder enthält. Der JSON fügt der Klasse, die funktioniert, zusätzliche Felder/Eigenschaften/Methoden hinzu, aber ich versuche, die Mitglieder in der Schnittstelle als schreibgeschützt definieren zu lassen. öffentliche Schnittstelle IComplexType { Zeichenfolge Name {get; einstellen; } Zeichenfolge JSON {get; einstellen; } [Bindable (true)] [TypeConverter (typeof (StringConverter))] Objekt PropertyInfo {get; einstellen; } } – Latency

Antwort

1

Gelöst!

benötigt, um die Konstruktor Argumente zu ändern, um die Anzahl der Iterationen entsprechen, da es zu Ldarg_1 als KeyValuePair härter war und seine Key & Wert respectivly zuweisen.

Durch die KVP zu beseitigen und einen zusätzlichen Parameter Bereitstellung der Konstruktor wie folgt definiert ist:

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); 

aufzurufen, ich extrahiert nur den Inhalt des KVP hier:

return (T) Activator.CreateInstance(TypeCollection[type], kvp.Key, kvp.Value, collection); 
Verwandte Themen