2017-09-11 3 views
1

내 C# 코드에서 BasicModel의 파생 클래스를 동적으로 생성하려고합니다. 그리고 파생 클래스의 가상 속성을 재정 의하여 기존 개체를 반환하려고합니다.IL 방출을 사용하여 존재하는 객체를 반환하는 가상 함수 생성

public class BasicModel 
{ 
    [IgnoreProperty] 
    public virtual CloudStorageAccount StorageAccount { get; } 
} 

여기 IL 부분이 있습니다. 그러나 나는 그 메소드를 호출하는 것을 끊임없이 null으로한다.

var IlGen2 = newMethod2.GetILGenerator(); 
Func<CloudStorageAccount> getStoredObj =() => parentModel.StorageAccount; 
IlGen2.Emit(OpCodes.Call, getStoredObj.GetMethodInfo()); 
IlGen2.Emit(OpCodes.Ldobj); 
IlGen2.Emit(OpCodes.Ret); 

무엇이 문제입니까? 아니면 더 좋은 방법이 있습니까?

고마워요.

+0

클래스와 연결하려는 대리인은 모든 인스턴스에서 동일 할 것입니까? 즉'() => parentModel.StorageAccount'는 동적 유형의 모든 인스턴스에 대해 동일합니까? –

+0

@ TitianCernicova-Dragomir thx 답장을 보내 주십시오. 'parentModel'은 타입마다 다릅니다. – Wizmann

답변

1

대리인이 유형의 모든 인스턴스에 대해 동일하기 때문에, 나는 대리자를 포함하고를 사용하는 정적 필드를 정의합니다 :

static void Main(string[] args) 
{ 

    var parentModel = new ContainerCloudStorageAccount { StorageAccount = new CloudStorageAccount() } ; 
    var type = CreateType("MyOverride",() => parentModel.StorageAccount); 
    var value = (BasicModel)type.GetConstructors().First().Invoke(new object[0]); 
    Console.WriteLine(value.StorageAccount); 
} 

public static Type CreateType(string name, Func<CloudStorageAccount> getter) 
{ 
    AppDomain myDomain = Thread.GetDomain(); 
    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(new AssemblyName("dynamicTypes"), AssemblyBuilderAccess.Run); 
    ModuleBuilder interfaceImplementationModule = myAsmBuilder.DefineDynamicModule("overrrides"); 

    TypeBuilder typeBuilder = interfaceImplementationModule.DefineType(name, 
     TypeAttributes.Public | TypeAttributes.Class, 
     typeof(BasicModel)); 

    var newMethod2 = typeBuilder.DefineMethod("get_StorageAccount", MethodAttributes.Virtual | MethodAttributes.Public, 
      typeof(CloudStorageAccount), Type.EmptyTypes 
    ); 
    typeBuilder.DefineMethodOverride(newMethod2, typeof(BasicModel).GetProperty("StorageAccount").GetGetMethod()); 

    var fieldInfo = typeBuilder.DefineField("getter", typeof(Func<CloudStorageAccount>), FieldAttributes.Static | FieldAttributes.Public); 

    var IlGen2 = newMethod2.GetILGenerator(); 
    IlGen2.Emit(OpCodes.Ldsfld, fieldInfo); 
    IlGen2.Emit(OpCodes.Call, typeof(Func<CloudStorageAccount>).GetMethod("Invoke")); 
    IlGen2.Emit(OpCodes.Ret); 

    typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); 
    var type = typeBuilder.CreateType(); 
    type.GetField("getter").SetValue(null, getter); 

    return type; 
} 

대리자가 더 있기 때문에 당신은 원래의 솔루션이 작동하지 않습니다 다음 메서드, 또한 해당 메서드의 대상 개체입니다. 따라서 대리자와 연결된 메서드를 호출하면 대리자에서 캡처 한 데이터가 없습니다.

+1

그것 바위! 고마워요! – Wizmann

+0

@Wizmann, 도와 드리겠습니다 :) –

관련 문제