[英]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();
}
}
变化:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.