I have a function that is building a dynamic method. As part of this dynamic method, it is calling an action known at generation time. As a minimal reproducible example, consider the following C# code:
using System.Reflection.Emit;
static class Program {
static Action MakeAction(Action action) {
DynamicMethod method = new DynamicMethod("test", null, null);
ILGenerator generator = method.GetILGenerator();
generator.Emit(OpCodes.Call, action.Method);
generator.Emit(OpCodes.Ret);
return method.CreateDelegate<Action>();
}
static void Main() {
MakeAction(() => Console.WriteLine("hello"))();
}
}
When I run this, I get a System.InvalidProgramException. What is the correct way to do this?
Use that delegate
If you have a delegate and you will invoke it you can use it exactly instead of creating a new delegate. Just
static Action MakeAction(Action action) => action.Static or instance delegates
Delegates can be made of static or instance methods so you must make specific call for both.
Static methods calls is simple: no
thisargument, justcallandret.For instance method calls you must load target object to stack and run
callvirt(null-check and allows virtual methods). ILGenerator does not allow you to load some object from other memory. DynamicMethod allows you to create static method that will be instance delegate. For this you must addthisargument and add owner class for method.Final solution:
System.Linq.Expressions
You can use Expressions for better runtime method building. It is much easier that DynamicMethod and Emit.
Creating delegate from delegate in Linq.Expressions:
Creating delegate from lambda-expression: