“操作可能destablize运行时”和DynamicMethod的值类型(“Operation c

2019-09-23 16:25发布

我想概括如下IL(从反射镜):

.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与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);

我得到的“操作可能会破坏运行时”异常。 该IL似乎等同于我,任何想法? ValueSource是值类型,这就是为什么我在这里做一个ref参数。

编辑

这里的ValueSource类型:

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

Answer 1:

更改参数传递给0/1(不是1/2):

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

因为它似乎动态方法为静态的,不是实例被创建(你原来的方法实例) - 因此ARG游戏关闭的一个。

(对不起,原来错误的答案-你可以把代码的其他位为true



文章来源: “Operation could destablize the runtime” and DynamicMethod with value types
标签: c# cil