繁体   English   中英

发送操作可能会使运行时不稳定以增加字段

[英]Emit Operation could destabilize the runtime for incrementing field

我使用相同的标题搜索了许多问题,但我没有找到适合我的答案。

所以我只是想增加我的类实例的一个字段:

class EmitTest
{
    private int _calls = 0;

    public EmitTest()
    {
        var callsFieldInfo = GetType().GetField("_calls", BindingFlags.NonPublic | BindingFlags.Instance);
        Debug.Assert(callsFieldInfo != null, "callsFieldInfo != null");

        var dynMethod = new DynamicMethod(new Guid().ToString(), typeof(void), null);
        var ilGenerator = dynMethod.GetILGenerator();
        ilGenerator.Emit(OpCodes.Nop);
        ilGenerator.Emit(OpCodes.Ldarg_0);
        ilGenerator.Emit(OpCodes.Dup);
        ilGenerator.Emit(OpCodes.Ldfld, callsFieldInfo);
        ilGenerator.Emit(OpCodes.Ldc_I4_1);
        ilGenerator.Emit(OpCodes.Add);
        ilGenerator.Emit(OpCodes.Stfld, callsFieldInfo);
        ilGenerator.Emit(OpCodes.Ret);

        Action delg = (Action)dynMethod.CreateDelegate(typeof(Action));
        delg();
    }
}

...

    static void Main(string[] args)
    {
        var test = new EmitTest();
    }

为什么它不起作用? 我想它与maxstack和局部变量有关,但我真的不知道。


关于代码:确保我为另一个类编写和反编译相同的代码,这里是:

class Program
{
    private int i = 0;
    static void Main(string[] args)
    {
        var test = new EmitTest();
        var prog = new Program();
        prog.Foo();
    }

    private void Foo()
    {
        i++;
    }
}

反编译:

.method private hidebysig instance void  Foo() cil managed
{
  // Размер кода:       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  dup
  IL_0003:  ldfld      int32 ConsoleApplication97.Program::i
  IL_0008:  ldc.i4.1
  IL_0009:  add
  IL_000a:  stfld      int32 ConsoleApplication97.Program::i
  IL_000f:  ret
} // end of method Program::Foo

所以它似乎是一样的

Action不接受任何争论,但你ldarg一个人。 你可能想要一个Action<EmitTest>

您编辑的反编译代码的差异似乎是此方法是采用隐式this参数的实例方法。

当你调用delg(); 您认为EmitTest实例是什么? 你从来没有指定一个。

您可以使用带有目标的CreateDelegate重载。 或使用Action<EmitTest>


这有效:

    class EmitTest
    {
        private int _calls = 0;

        public EmitTest()
        {
            var callsFieldInfo = GetType().GetField("_calls", BindingFlags.NonPublic | BindingFlags.Instance);
            Debug.Assert(callsFieldInfo != null, "callsFieldInfo != null");

            var dynMethod = new DynamicMethod(new Guid().ToString(), typeof(void), new[] { typeof(EmitTest) } /*added*/, true /*added*/);
            var ilGenerator = dynMethod.GetILGenerator();
            ilGenerator.Emit(OpCodes.Nop);
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Dup);
            ilGenerator.Emit(OpCodes.Ldfld, callsFieldInfo);
            ilGenerator.Emit(OpCodes.Ldc_I4_1);
            ilGenerator.Emit(OpCodes.Add);
            ilGenerator.Emit(OpCodes.Stfld, callsFieldInfo);
            ilGenerator.Emit(OpCodes.Ret);

            Action delg = (Action)dynMethod.CreateDelegate(typeof(Action), this /*added*/);
            delg();
        }
    }

变化:

  1. 将代表绑定到目标
  2. 指定参数类型(您告诉构建器没有参数)
  3. 启用私人访问

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM