2017-10-15 26 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이 상당히입니다 :

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의 내용을 추출 Refection보다 쉬움 Empty – MickyD

+1

게시 한 코드가 생성자 인수를 배킹 필드에 할당하는 것 같습니다. 작동하지 않습니까? –

+0

뭔가 올바르게 작동하지 않습니다. 형식을 컴파일하고 반환합니다. 인스턴스를 생성 할 수 있습니다. 검사 할 때 일부 필드/속성이 누락되었습니다. 예를 들어, 3 개의 필드를 포함하는 Interface 클래스가 있어야합니다. JSON은 작동하는 클래스에 추가 필드/속성/메서드를 추가하지만 인터페이스에서 읽기 전용으로 멤버를 정의하려고합니다. 공용 인터페이스 IComplexType { 문자열 이름 {get; 세트; } string JSON {get; 세트; } [바인딩 가능 (true)] [TypeConverter (typeof (StringConverter))]개체 PropertyInfo {get; 세트; } } – Latency

답변

1

해결 된!

Ldarg_1이 KeyValuePair로 더 어려웠고 해당 키 & 값을 각각 할당하기 때문에 생성자 인수를 반복 횟수와 일치하도록 변경해야했습니다. KVP를 제거하고 생성자로 정의 추가 매개 변수를 제공함으로써

은 다음과 같습니다

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