【发布时间】:2016-06-17 00:07:36
【问题描述】:
我正在通过TypeBuilder 构建我自己的类型,并且我正在尝试将调用从不同对象收集的methodInfo 添加到此方法中。
问题是我不知道如何使用ILGenerator.Emit 或ILGenerator.EmitCall。
我尝试使用il.EmitCall(OpCodes.Call, methodInfo, arguments) 和il.Emit(OpCodes.Call, methodInfo),但它们都不起作用。我总是收到这个错误:
[InvalidProgramException: Common Language Runtime detected an invalid program.]
MyImplementationController.Hello1() +0
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +192
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +155
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +19
这是我的代码:
foreach (var methodInfo in methodInfosFromSomewhere)
{
var arguments = methodInfo.GetParameters().Select(a => a.ParameterType).ToArray();
MethodBuilder mb = tb.DefineMethod(
methodInfo.Name,
MethodAttributes.Final | MethodAttributes.Public,
CallingConventions.HasThis,
methodInfo.ReturnType,
arguments);
// method
ILGenerator il = mb.GetILGenerator();
int numParams = arguments.Length;
for (byte x = 0; x < numParams; x++)
{
//il.Emit(OpCodes.Ldarg_S, x);
il.Emit(OpCodes.Ldstr, x);
}
//il.EmitCall(OpCodes.Call, methodInfo, arguments);
il.Emit(OpCodes.Call, methodInfo);
il.Emit(OpCodes.Ret);
}
@编辑
我终于知道(可能)哪里出了问题!当我调用Emit.Call 时,我不想调用此对象中的方法。我想从另一个对象调用方法。
请看这个例子:
// this is interface that we want to 'decorate'
public interface IMyInterface
{
MyResponse Hello1();
MyResponse Hello2(MyRequest request);
MyResponse Hello3(MyRequest request);
}
public class MyImplementation : IMyInterface
{
public MyResponse Hello1()
{
return new MyResponse { Name = "empty" };
}
// ... rest of implementation, it doesn't matter
}
我要生成的类是这样的:
public class GeneratedClass : ApiController
{
public MyInterface myImplementation { get; set; }
public MyResponse Hello1()
{
return myImplementation.Hello1();
}
// ... rest of implementation, it doesn't matter
}
如您所见,我想从其他对象调用方法。我知道如何为对象创建属性,但我不知道如何从其他对象调用方法
【问题讨论】:
-
带有 OpCode OpCodes.Ldstr 的指令需要一个字符串作为参数,而不是一个字节。
-
你事先知道方法的参数类型吗?以完全动态的方式生成呼叫并不适合胆小的人。您必须发出正确的(类型安全的)代码来加载每个参数。
-
我得到了
MethodInfo的存储位置。我什么都不知道 -
通过调用
DynamicAssembly.Save(...)将生成的程序集写入文件,然后使用peverify.exe分析您的方法无效的原因。 -
如果您不能通过这种方式解决它,您可以创建一个可编译的示例来重现您的问题的情况,并且可以对其进行全面分析。
标签: c# reflection reflection.emit