2017-09-11 8 views
1

私のC#コードでBasicModelの派生クラスを動的に生成したいと考えています。そして、私は存在するオブジェクトを返すために、派生クラスの仮想プロパティをオーバーライドする必要があります。IL Emitを使用して存在するオブジェクトを返す仮想関数を生成する

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が喜んで:) –

関連する問題