I want to call a function with a parameter with the reflection.emit API. In the following is what I have at the moment. But when I run it, it throws the following exception: System.InvalidProgramException : Common Language Runtime detected an invalid program. So my question is what I have wrong in my code snippet below? Can someone help me out?
public class Test
{
public void test()
{
Func<int, long> realSquareFunc = (val) => val * val;
Type[] methodArgs = { typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Save parameter on stack
il.Emit(OpCodes.Call, realSquareFunc.Method); // Call function with input as parameter
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<int, long>)squareIt.CreateDelegate(realSquareFunc.GetType());
var result = myMethod.Invoke(4); // Should be 16 (4*4)
}
}
Your code would work as is if the called method was a static method:
However, the
realSquareFunc = (val) => val * vallambda is actually compiled as an instance method of a hidden class. To call an instance method, the instance must be pushed onto the stack first, before the method arguments. Instance method calls also typically use theCallvirtopcode (regardless of whether they're virtual, because this opcode does null reference checking):Calling the target method of a lambda directly is more complicated due to the compiler-generated class involved, but if you want to call a delegate in general it works like this: