ILGenerator 实例化对象并调用实例方法
ILGenerator instantiate object and call instance method
我正在尝试构造泛型类型的实例并调用该实例的方法。然后return方法的结果。
var genericType = typeof(GenericType<>).MakeGenericType(typeof(TOutput));
il.DeclareLocal(genericType);
var instanceMethod = genericType.GetMethod("MethodName", new Type[0]);
il.Emit(OpCodes.Call, instanceMethod);
il.Emit(OpCodes.Ret);
我一直收到 'System.InvalidProgramExecution' 异常。
GenericType class 看起来像这样
public class GenericType<T>
{
public T MethodName()
{
...
}
}
试试这个代码:
var il = mbuilder.GetILGenerator();
var genericType = typeof(GenericType<>).MakeGenericType(typeof(TOutput));
il.Emit(OpCodes.Newobj, genericType.GetConstructor(Type.EmptyTypes));
il.EmitCall(OpCodes.Callvirt, genericType.GetMethod("MethodName", Type.EmptyTypes), null);
il.Emit(OpCodes.Ret);
确定需要为特定函数发出什么 IL 的一种简单方法是手动编写要生成的代码,然后使用 ILDASM 查看编译器创建的 IL。
举个例子...
C# 方法复制...
public static TOutput DoWork()
{
var generic = new GenericType<TOutput>();
var ret = generic.MethodName();
return ret;
}
生成的 IL...
.method public hidebysig static class App.TOutput
DoWork() cil managed
{
// Code size 15 (0xf)
.maxstack 1
.locals init ([0] class App.GenericType`1<class App.TOutput> generic,
[1] class App.TOutput 'ret')
IL_0000: newobj instance void class App.GenericType`1<class App.TOutput>::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt instance !0 class App.GenericType`1<class App.TOutput>::MethodName()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: ret
} // end of method Program::DoWork
有关如何发出和调用此 IL 的示例...
var retType = typeof(TOutput);
var type = typeof(GenericType<>);
var genericType = type.MakeGenericType(retType);
var constructor = genericType.GetConstructor(Type.EmptyTypes);
var methodDef = genericType.GetMethod("MethodName", Type.EmptyTypes);
var newMethod = new DynamicMethod("MyMethod", retType, Type.EmptyTypes);
var generator = newMethod.GetILGenerator();
generator.DeclareLocal(genericType);
generator.DeclareLocal(retType);
generator.Emit(OpCodes.Newobj, constructor);
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, methodDef, null);
generator.Emit(OpCodes.Stloc_1);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ret);
var ret = newMethod.Invoke(null, null);
Console.WriteLine(ret); // App.TOutput
支持类...
public class GenericType<T> where T : new()
{
public T MethodName()
{
return new T();
}
}
public class TOutput
{
}
我正在尝试构造泛型类型的实例并调用该实例的方法。然后return方法的结果。
var genericType = typeof(GenericType<>).MakeGenericType(typeof(TOutput));
il.DeclareLocal(genericType);
var instanceMethod = genericType.GetMethod("MethodName", new Type[0]);
il.Emit(OpCodes.Call, instanceMethod);
il.Emit(OpCodes.Ret);
我一直收到 'System.InvalidProgramExecution' 异常。
GenericType class 看起来像这样
public class GenericType<T>
{
public T MethodName()
{
...
}
}
试试这个代码:
var il = mbuilder.GetILGenerator();
var genericType = typeof(GenericType<>).MakeGenericType(typeof(TOutput));
il.Emit(OpCodes.Newobj, genericType.GetConstructor(Type.EmptyTypes));
il.EmitCall(OpCodes.Callvirt, genericType.GetMethod("MethodName", Type.EmptyTypes), null);
il.Emit(OpCodes.Ret);
确定需要为特定函数发出什么 IL 的一种简单方法是手动编写要生成的代码,然后使用 ILDASM 查看编译器创建的 IL。
举个例子...
C# 方法复制...
public static TOutput DoWork()
{
var generic = new GenericType<TOutput>();
var ret = generic.MethodName();
return ret;
}
生成的 IL...
.method public hidebysig static class App.TOutput
DoWork() cil managed
{
// Code size 15 (0xf)
.maxstack 1
.locals init ([0] class App.GenericType`1<class App.TOutput> generic,
[1] class App.TOutput 'ret')
IL_0000: newobj instance void class App.GenericType`1<class App.TOutput>::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt instance !0 class App.GenericType`1<class App.TOutput>::MethodName()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: ret
} // end of method Program::DoWork
有关如何发出和调用此 IL 的示例...
var retType = typeof(TOutput);
var type = typeof(GenericType<>);
var genericType = type.MakeGenericType(retType);
var constructor = genericType.GetConstructor(Type.EmptyTypes);
var methodDef = genericType.GetMethod("MethodName", Type.EmptyTypes);
var newMethod = new DynamicMethod("MyMethod", retType, Type.EmptyTypes);
var generator = newMethod.GetILGenerator();
generator.DeclareLocal(genericType);
generator.DeclareLocal(retType);
generator.Emit(OpCodes.Newobj, constructor);
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, methodDef, null);
generator.Emit(OpCodes.Stloc_1);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ret);
var ret = newMethod.Invoke(null, null);
Console.WriteLine(ret); // App.TOutput
支持类...
public class GenericType<T> where T : new()
{
public T MethodName()
{
return new T();
}
}
public class TOutput
{
}