I use Mono.Cecil to inject some IL code into an auto-implemented set of properties. The problem is that I can get a link to it from the TypeDefinition.Fields object, but when I insert the ldfld instruction (after the ldarg.0 instruction) with this link, it causes the application to fail, and the CLR invalid program detected exception is thrown. I also tried decompiling ILSpy and got a Mono.Cecil argument out of range exepction in get_Item(int32) method . So itβs as if Iβm trying to access the backup fields before the compiler Mono.Cecil it, but somehow Mono.Cecil can see it when the assembly loads.
public class ILTesting { public int Counter { get; set; } }
Here's what the setter looks like before injection:
IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: stfld int32 SyringeWpfTest.ILTesting::'<Counter>k__BackingField' IL_0007: ret
Here is the injection code:
var fieldName = "<" + property.Name + ">k__BackingField"; var fieldRef = ilTestType.Fields.Single(field => field.Name == fieldName); var setterInstruction = property.SetMethod.Body.Instructions; setterInstructions.Insert(0, Instruction.Create(OpCodes.Brfalse_S, setterInstructions.Last())); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ldloc_0)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Stloc_0)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ceq)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ldc_I4_0)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ceq)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ldarg_1)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ldfld, reference)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Ldarg_0)); setterInstructions.Insert(0, Instruction.Create(OpCodes.Nop));
And this is IL, I get:
IL_0000: nop IL_0001: ldarg.0 IL_0002: ldfld int32 SyringeWpfTest.ILTesting::'<Counter>k__BackingField' IL_0007: ldarg.1 IL_0008: ceq IL_000a: ldc.i4.0 IL_000b: ceq IL_000d: stloc.0 IL_000e: ldloc.0 IL_000f: brfalse.s IL_001a IL_0011: nop IL_0012: ldarg.0 IL_0013: ldarg.1 IL_0014: stfld int32 SyringeWpfTest.ILTesting::'<Counter>k__BackingField' IL_0019: nop IL_001a: ret
Thus, the injection code did not break, the reference to the support field exists, but in IL it seems that there is no support field.