Reputation: 64
I'm trying to create a call to a proxy method in generated class with opcodes and I get ExecutionEngineException
. This method must receive return type as first argument and array of arguments from calling method.
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);
And the second problem is that i receive firstly an array of args and then return type.
Upvotes: 1
Views: 459
Reputation: 417
OpCodes.ldtoken does not put Type on stack. It puts RuntimeTypeHandle. To get type you should do something like that:
var getTypeMethod = typeof (Type).GetMethod("GetTypeFromHandle");
methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType);
methodILGen.Emit(OpCodes.Call, getTypeMethod);
methodILGen.Emit(OpCodes.Ldloc, _args);
Upvotes: 4