Action
does not take any arguments, yet you ldarg
one. You probably want an Action<EmitTest>
.
The difference to the decompiled code you edited in seems to be that this method is an instance method taking an implicit this
argument.
When you call delg();
what instance of EmitTest
would you think this runs on? You never specified one.
You can use the overload of CreateDelegate
that takes a target. Or use an Action<EmitTest>
.
This works:
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();
}
}
Changes:
- Bind the delegate to a target
- Specify argument types (you told the builder that there are no arguments)
- Enable private access