我用相同的标题搜索了许多问题,但我没有找到适合我的答案。
所以我只想尝试增加类实例的字段:
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
所以它似乎是相同的
答案 0 :(得分:4)
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();
}
}
的变化: