6

我想发出一个有变量的方法,我可以做到。但是,我想在该变量中存储一个 MethodInfo 对象,它是对不同(非发出)方法的引用。

我可以发出操作码来调用 typeof(someClass).GetMethod(...),但如果我可以简单地为此 MethodInfo 加载一个令牌并将其直接烘焙到变量中,效率会更高。

所以,换个说法,我试图找出它的可能性,让我们说一个“加载对象”操作码,并在发射时将一个对象传递给它,该对象将在运行时加载到堆栈中。(当我尝试这个时,OpCodes.Ldobj 给出了某种错误)。或者,我是否被迫发出将在运行时执行此操作的操作码?

4

1 回答 1

10

你不能只在 IL 中加载任何通用对象,因为没有办法将它存储在 IL 中(除了一些特殊类型,如string)。您可以使用序列化(对于支持它的类型)来解决这个问题,但我认为这不是您想要的。此外,ldobj服务于完全不同的目的。

但是您可以通过MethodInfo与 C# 对运算符所做的非常相似的方式来执行此typeof操作。这意味着:

  1. 使用ldtoken指令得到一个RuntimeMethodHandle
  2. 打电话MethodBase.GetMethodFromHandle()要一个MethodBase
  3. 将其投射到MethodInfo

生成返回 的方法的整个代码MethodInfo如下所示:

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());
于 2013-02-10T13:10:14.797 回答