I'm using Mono.Cecil for rewriting some assemblies. Given a generic class with a string field for example. I want to generate code into a method of this class which writes into this field. This is the code to achieve that:
var origInstanceField = type.Fields.First(fld => fld.Name.Equals("_original"));
InsertBeforeReturn(instanceMethod.Body, new[]
{
Instruction.Create(OpCodes.Ldarg_0),
Instruction.Create(OpCodes.Ldstr, "genCodeToOriginal"),
Instruction.Create(OpCodes.Stfld, origInstanceField)
});
For non-generic classes it works like a charm. For generic classes it creates bad IL. If you take a look on the decompiled IL you can spot the difference compared to the same instructions emitted by the compiler.
.method public hidebysig instance void FillFields() cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldstr "non-gen code to non-gen field"
L_0007: stfld string TestConsole.GenericClass`1<!T>::_original
L_0017: ldarg.0
L_0018: ldstr "genCodeToOriginal"
L_001d: stfld string TestConsole.GenericClass`1::_original
L_0022: ret
}
The field reference points to the open generic type [GenericClass<>] and not to the to be constructed type [GenericClass< T>].
I tried also with a static field with the same result.
Any idea how can I get to the right FieldDefinition?
I've managed to find a solution by looking at the source code of Anotar (https://github.com/Fody/Anotar). The trick is to create a field reference with a type definition refering to an instantiated generic, not the original one.
var declaringType = new GenericInstanceType(definition.DeclaringType);
foreach (var parameter in definition.DeclaringType.GenericParameters)
{
declaringType.GenericArguments.Add(parameter);
}
return new FieldReference(definition.Name, definition.FieldType, declaringType);
Using this transformation on the FieldDefinition coming from type gives the right FieldReference. Feeding the generic parameters to generic arguments is a little odd but makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With