How do I emit a method with a pre-loaded MethodInfo local variable?
Asked Answered
L

1

6

I would like to emit a method that has a variable, which I can do. But, I would like to store in that variable a MethodInfo object, which is a reference to a different (non emitted) method.

I could emit the opcodes to call typeof(someClass).GetMethod(...), but it would be more efficient if I could simply load a token for this MethodInfo and bake it directly into the variable.

So, to rephrase, I'm trying to find out of its possible to emit , let's say a "load object" opcode and pass it an object at emit-time that will be loaded onto the stack at runtime. (OpCodes.Ldobj gave some kind of error when I tried this). Or, am I forced to emit opcodes that will do this at runtime?

Loiretcher answered 10/2, 2013 at 7:2 Comment(3)
I think this is possible. Eric Lippert once blogged about a possible infoof C# operator that would use this.Musaceous
Could you give a little context on the reason behind, to make the problem a little clearer for me/us?Hanni
@Musaceous The article you're talking about is about the syntactical problems of infoof, not how it could be implemented.Transubstantiate
T
10

You can't just load any general object in IL, because there is no way to store it in IL (with the exception of some special types like string). You could work around that using serialization (for types that support it), but I don't think that's what you want. Also, ldobj serves quite a different purpose.

But you can do this for MethodInfo in a way that's very similar to what C# does for the typeof operator. That means:

  1. using the ldtoken instruction to get a RuntimeMethodHandle
  2. calling MethodBase.GetMethodFromHandle() to get a MethodBase
  3. cast it to MethodInfo

The whole code to generate a method that returns the MethodInfo could look like this:

MethodInfo loadedMethod = …;
var getMethodMethod = typeof(MethodBase).GetMethod(
    "GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) });

var createdMethod = new DynamicMethod(
    "GetMethodInfo", typeof(MethodInfo), Type.EmptyTypes);

var il = createdMethod.GetILGenerator();
il.Emit(OpCodes.Ldtoken, loadedMethod);
il.Emit(OpCodes.Call, getMethodMethod);
il.Emit(OpCodes.Castclass, typeof(MethodInfo));
il.Emit(OpCodes.Ret);

var func = (Func<MethodInfo>)createdMethod.CreateDelegate(typeof(Func<MethodInfo>));
Console.WriteLine(func());
Transubstantiate answered 10/2, 2013 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.