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

Popular posts from this blog

html - Firefox flex bug applied to buttons? -

html - Missing border-right in select on Firefox -

c# - two queries in same method -