Jan 14, 2014 at 1:43 PM
Edited Jan 14, 2014 at 1:45 PM
I'm trying to create a mutator based off the ILMutator sample which modifies some classes to make them freezable if they have a certain attribute. I inject a boolean field "isFrozen" and a method "FreezablePrecondition" which throws
an exception if isFrozen is true. I then inject a call to that method into the setters of properties.
It all works fine until I try and mutate the IL of a class with generic parameters. Even then the mutator program runs fine, but when I try to invoke a method I've injected I get the error:
System.InvalidOperationException: Could not execute the method because either the method itself or the containing type is not fully instantiated.
at FreezableRewriter.TestAssembly.Generic`1.set_Test(T value)
peverify doesn't detect any problems with the assembly.
In reflector the IL for FreezablePrecondition() looks like this:
.method private hidebysig instance void FreezablePrecondition() cil managed
.custom instance void [FreezableHelper]FreezableHelper.ReferenceFreezablePreconditionAttribute::.ctor()
.locals init (
 bool flag)
L_0002: ldfld bool FreezableRewriter.TestAssembly.Generic`1::isFrozen
L_000c: brtrue.s L_001a
L_000f: ldstr "The instance is frozen and cannot be modified."
L_0014: newobj instance void [FreezableHelper]FreezableHelper.InstanceFrozenException::.ctor(string)
As you can see it checks a local boolean (isFrozen) and throws an exception if the value is true. Again, this all works fine if the class doesn't have any generic parameters.
I tried creating a method that does something similar manually and compared the IL. The only real difference is this line:
L_0002: ldfld bool FreezableRewriter.TestAssembly.Generic`1<!T>::test
Where, compared to the line in the injected code, the field reference has "<!T>" on the end of the location. I'm unsure how to do this in CCI (I've tried using a SpecializedFieldReference but it didn't help).
Can anyone point me in the right direction here?