2009-08-14 25 views
6

Tôi đang cố gắng để khái quát các IL sau (từ Reflector):"Operation thể destablize thời gian chạy" và DynamicMethod với kiểu giá trị

.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 
} 

Tuy nhiên, khi tôi cố gắng và tái sản xuất IL này với DynamicMethod:

 [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); 

Tôi nhận được ngoại lệ là "Thao tác có thể làm mất ổn định thời gian chạy". IL có vẻ giống hệt với tôi, bất kỳ ý tưởng nào? ValueSource là một loại giá trị, đó là lý do tại sao tôi đang làm một tham số ref ở đây.

EDIT

Dưới đây là các loại ValueSource:

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

Bất kỳ cơ hội của (hy vọng đơn giản) ValueSource vì vậy chúng tôi có thể tái sản xuất ...? –

+1

Ngoài ra - các loại giá trị thực sự nên không thay đổi được, điều này sẽ làm cho sự kiện này trở thành ... –

Trả lời

4

Thay đổi args để 0/1 (không phải 1/2):

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

vì phương pháp năng động có vẻ như được tạo ra như là tĩnh, không phải ví dụ (phương thức ban đầu của bạn là instance) - do đó các args bị tắt bởi một.

(xin lỗi vì sự sai câu trả lời ban đầu - bạn có thể để lại các bit khác của mã như true)

+0

Vâng, đúng vậy. Lần tới tôi sẽ làm cho phương thức mẫu của tôi tĩnh. –

Các vấn đề liên quan