2009-08-14 20 views
6

我想概括如下IL(從反射鏡):用DynamicMethod的「操作可能destablize運行時」和DynamicMethod的值類型

.method private hidebysig instance void SetValue(valuetype Test.TestFixture/ValueSource& thing, string 'value') cil managed 
{ 
    .maxstack 8 
    L_0000: nop 
    L_0001: ldarg.1 
    L_0002: ldarg.2 
    L_0003: call instance void Test.TestFixture/ValueSource::set_Value(string) 
    L_0008: nop 
    L_0009: ret 
} 

然而,當我試圖重現此IL:

 [Test] 
    public void Test_with_DynamicMethod() 
    { 
     var sourceType = typeof(ValueSource); 
     PropertyInfo property = sourceType.GetProperty("Value"); 

     var setter = property.GetSetMethod(true); 
     var method = new DynamicMethod("Set" + property.Name, null, new[] { sourceType.MakeByRefType(), typeof(string) }, true); 
     var gen = method.GetILGenerator(); 

     gen.Emit(OpCodes.Ldarg_1); // Load input to stack 
     gen.Emit(OpCodes.Ldarg_2); // Load value to stack 
     gen.Emit(OpCodes.Call, setter); // Call the setter method 
     gen.Emit(OpCodes.Ret); 

     var result = (SetValueDelegate)method.CreateDelegate(typeof(SetValueDelegate)); 

     var source = new ValueSource(); 

     result(ref source, "hello"); 

     source.Value.ShouldEqual("hello"); 
    } 

    public delegate void SetValueDelegate(ref ValueSource source, string value); 

我收到「操作可能會破壞運行時」的異常。 IL似乎和我一樣,有什麼想法? ValueSource是一個值類型,這就是我在這裏做一個ref參數的原因。

編輯

這裏的ValueSource類型:

 public struct ValueSource 
    { 
     public string Value { get; set; } 
    } 
+0

(希望簡單)ValueSource的任何機會,所以我們可以重現...? – 2009-08-14 13:32:03

+1

此外 - 值類型應該是不可改變的,這將使得這種模式不可行。 – 2009-08-14 13:33:15

回答

4

更改參數傳遞給0/1(不是1/2):

gen.Emit(OpCodes.Ldarg_0); // Load input to stack 
    gen.Emit(OpCodes.Ldarg_1); // Load value to stack 

因爲動態方法似乎被創建爲靜態的,而不是實例(你的原始方法是實例) - 因此參數被關閉。

(對不起,原來錯誤的答案 - 你可以把代碼的其他位爲true

+0

沒錯,就是這樣。下次我將使我的模板方法變爲靜態。 – 2009-08-14 14:05:54

相關問題