如何使用预先加载的MethodInfo局部变量发出方法?

时间:2013-02-10 07:02:39

标签: c# .net reflection.emit

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

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

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

1 个答案:

答案 0 :(得分:9)

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

但是你可以以MethodInfo的方式执行此操作,其方式与C#对typeof运算符的方式非常相似。这意味着:

  1. 使用ldtoken指令获取RuntimeMethodHandle
  2. 致电MethodBase.GetMethodFromHandle()以获取MethodBase
  3. 将其投放到MethodInfo
  4. 生成返回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());