使用 IL Emit 生成虚函数,其中 returns 现有对象
Using IL Emit to generate a virtual function which returns an existed object
我想在我的 C# 代码中动态生成 BasicModel
的派生 class。我想将派生 class 中的虚拟 属性 覆盖为 return 一个已存在的对象。
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);
有什么问题吗?或者有更好的方法吗?
非常感谢。
由于委托对于该类型的所有实例都是相同的,我将定义一个包含委托的静态字段并使用它:
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;
}
您原来的解决方案不起作用,因为委托不仅仅是一种方法,它还是该方法的目标对象。因此,如果您只是调用与委托关联的方法,它将不会拥有您在委托中捕获的数据。
我想在我的 C# 代码中动态生成 BasicModel
的派生 class。我想将派生 class 中的虚拟 属性 覆盖为 return 一个已存在的对象。
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);
有什么问题吗?或者有更好的方法吗?
非常感谢。
由于委托对于该类型的所有实例都是相同的,我将定义一个包含委托的静态字段并使用它:
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;
}
您原来的解决方案不起作用,因为委托不仅仅是一种方法,它还是该方法的目标对象。因此,如果您只是调用与委托关联的方法,它将不会拥有您在委托中捕获的数据。