c# - Mono.Cecil auto-implemented property accessing backing field -
i using mono.cecil
inject il
code in auto-implemented property setter. problem is, can reference typedefinition.fields
object when inject ldfld
instruction (after ldarg.0
instruction ofc) reference causes application break, , clr invalid program detected
exception raised. tried decompile ilspy
, got exception mono.cecil argument out of range exepction in get_item(int32) method
. it's trying access backing field before it's created compiler, somehow mono.cecil
can see when loads assembly.
public class iltesting { public int counter { get; set; } }
this how setter looks before injection:
il_0000: ldarg.0 il_0001: ldarg.1 il_0002: stfld int32 syringewpftest.iltesting::'<counter>k__backingfield' il_0007: ret
here 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 il 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
so injection code didn't break, reference backing field exists, in il
looks there not backing field @ all.
problem solved! it's wasn't property, way il
works. made full property code:
private int _counter; public int counter { { return _counter; } set { if (_counter != value) { _counter = value; notifyui(); } } }
i opened assembly in ilspy
, il
code injected auto-implemented property. decompiled il
see c#
code looks after decompileing, , code looked like:
private int _counter; public int counter { { return _counter; } set { bool flag = _counter != value; //this thing made life hard few days! if (flag) { _counter = value; notifyui(); } } }
so, problem missing local variable on methods stack frame. after inserted local variable in method, work perfect.
myproperty.setmethod.body.variables.add(new variabledefinition(assembly.mainmodul.import(typeof(bool)));
Comments
Post a Comment