我正在尝试使用操作码在生成的类中创建对代理方法的调用,然后我得到ExecutionEngineException
。此方法必须接收返回类型作为第一个参数和来自调用方法的参数数组。
var methodILGen = methodBuilder.GetILGenerator();
if (methodInfo.ReturnType != typeof(void))
{
var method = typeBuilder.BaseType.GetMethod("proxyCaller");
var args = methodInfo.GetParameters();
var lb = methodILGen.DeclareLocal(methodInfo.ReturnType);
LocalBuilder _args = methodILGen.DeclareLocal(typeof(object[]));
methodILGen.Emit(OpCodes.Ldc_I4_S, args.Length);
methodILGen.Emit(OpCodes.Newarr, typeof(object));
methodILGen.Emit(OpCodes.Stloc, _args);
methodILGen.Emit(OpCodes.Ldloc, _args);
for (int i = 0; i < args.Length; i++)
{
methodILGen.Emit(OpCodes.Ldc_I4_S, i);
methodILGen.Emit(OpCodes.Ldarg_S, i + 1);
methodILGen.Emit(OpCodes.Stelem_Ref);
methodILGen.Emit(OpCodes.Ldloc, _args);
}
methodILGen.Emit(OpCodes.Stloc, _args);
methodILGen.Emit(OpCodes.Ldarg_0); // instance pointer
methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType); //return type
methodILGen.Emit(OpCodes.Ldloc, _args); //args list
methodILGen.Emit(OpCodes.Call, method);//, new Type[0]);
if (methodInfo.ReturnType.IsValueType || methodInfo.ReturnType.IsEnum) methodILGen.Emit(OpCodes.Unbox_Any, lb.LocalType);
}
methodILGen.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
第二个问题是我首先收到一个args数组然后返回类型。
答案 0 :(得分:4)
OpCodes.ldtoken不会将Type放在堆栈上。它放了RuntimeTypeHandle。要获得类型,你应该做类似的事情:
var getTypeMethod = typeof (Type).GetMethod("GetTypeFromHandle");
methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType);
methodILGen.Emit(OpCodes.Call, getTypeMethod);
methodILGen.Emit(OpCodes.Ldloc, _args);