2009-08-14 6 views
6

Estoy tratando de generalizar la siguiente IL (de reflector):"Operación podría desestabilizar el tiempo de ejecución" y DynamicMethod con tipos de valor

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

Sin embargo, cuando intento reproducir este IL con 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); 

Tengo una excepción de "La operación podría desestabilizar el tiempo de ejecución". El IL parece idéntico a mí, ¿alguna idea? ValueSource es un tipo de valor, por lo que estoy haciendo un parámetro ref aquí.

EDITAR

Aquí está el tipo ValueSource:

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

alguna posibilidad de que la (esperemos sencilla) ValueSource para que podamos reproducir ...? –

+1

Además, los tipos de valores deberían ser inmutables, lo que haría que este discutible ... –

Respuesta

4

Cambiar los argumentos a 0/1 (no 1/2):

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

porque el método dinámico que parece para ser creado como estático, no instancia (su método original es instancia) - por lo tanto, los argumentos están desactivados en uno.

(lo siento por la respuesta equivocada originales - se puede dejar el otro trozo de código que true)

+0

Sí, eso fue todo. La próxima vez haré mi método de plantilla estático. –

Cuestiones relacionadas