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

Jay*_*van 5 .net c# reflection.emit

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

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

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

svi*_*ick 9

你不能只在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());
Run Code Online (Sandbox Code Playgroud)