I am trying to dynamically build a type with a method that calls into an external delegate by using System.Reflection.Emit
. However when I try to call this method, my program crashes with the exception in the title at the method call. Here's my code so far:
private static void TestMethodReal() => Console.Out.WriteLine("Inside TestMethod");
// In Main()
var method = typeof(Program).GetMethod(nameof(TestMethodReal), BindingFlags.Static | BindingFlags.NonPublic)!;
var builder = MyTypeBuilder.GetTypeBuilder("TestType");
var testMethod = builder.DefineMethod("TestMethod", MethodAttributes.Public, typeof(void), Type.EmptyTypes);
var generator = testMethod.GetILGenerator();
generator.EmitCall(OpCodes.Callvirt, method, null);
generator.Emit(OpCodes.Ret);
dynamic inst = Activator.CreateInstance(builder.CreateType()!)!;
inst.TestMethod(); // <--- Exception is thrown here
The MyTypeBuilder
class and GetTypeBuilder
method is from this answer, slightly modified to accept a parameter for the type's name.
This program is supposed to create a new dynamic class with a method called TestMethod
that calls the actual TestMethodReal
method, instantiate the class, and call the method.
What am I missing?
CodePudding user response:
You're using the wrong dispatch mechanism!
OpCodes.Callvirt
is for virtual method calls, eg. overridable instance methods, the resolution of which needs to be deferred until runtime.
For static method invocation you'll want a plain old OpCodes.Call
instruction instead:
generator.EmitCall(OpCodes.Call, method, Types.EmptyTypes);