2009-08-18 55 views
5

如何为具有out参数的代理定义DynamicMethod,如下所示?DynamicMethod和out-parameters?

public delegate void TestDelegate(out Action a); 

比方说,我只是想那台a参数null当我调用该方法的方法。

请注意,我知道处理此问题的一种可能更好的方法是使该方法返回Action委托,但这只是大型项目的简化部分,并且所讨论的方法已经返回值I除了它之外,还需要处理out参数,因此是个问题。

我尝试这样做:

using System; 
using System.Text; 
using System.Reflection.Emit; 

namespace ConsoleApplication8 
{ 
    public class Program 
    { 
     public delegate void TestDelegate(out Action a); 

     static void Main(String[] args) 
     { 
      var method = new DynamicMethod("TestMethod", typeof(void), 
       new Type[] { typeof(Action).MakeByRefType() }); 
      var il = method.GetILGenerator(); 

      // a = null; 
      il.Emit(OpCodes.Ldnull); 
      il.Emit(OpCodes.Starg, 0); 

      // return 
      il.Emit(OpCodes.Ret); 

      var del = (TestDelegate)method.CreateDelegate(typeof(TestDelegate)); 
      Action a; 
      del(out a); 
     } 
    } 
} 

不过,我得到这个:

VerificationException was unhandled: 
Operation could destabilize the runtime. 

del(out a);线。

请注意,如果我注释掉在堆栈上加载null并尝试将其存储到参数中的两行,该方法无例外地运行。


编辑:这是最好的方法?

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Ldnull); 
il.Emit(OpCodes.Stind_Ref); 
+0

真的需要创建一个动态方法吗?为什么不直接在可以配置为在运行时执行所需操作的类中实现该方法? – 2009-08-18 09:32:30

+0

它必须是一个动态方法,这是一个最后停止的优化工作,可以让一个巨大的基于反射的调用树更快地执行。到目前为止,使用动态方法方法的开销与现有代码相比似乎减少了大约85%,这是每秒钟会被调用数千次的代码。测量表明,相当多的cpu与现有的反射代码捆绑在一起。 – 2009-08-18 09:37:24

回答

6

一种out参数仅仅是一个ref参数与施加于该参数的OutAttribute

要存储到by-ref参数,您需要使用stind操作码,因为参数本身是一个指向对象实际位置的托管指针。

ldarg.0 
ldnull 
stind.ref