2009-08-18 53 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