Hi Jean-Baptiste,
I stumbled upon a pb with fields in generic classes
Suppose you have a generic class A defined as follows
public class A<T>
{
public static int field = 0;
public int Property { get { return 0; } }
public int PropertyCorrect { get { return field; } }
}
and you basically want to have Property return field instead of 0
If I open the original assembly in reflector, I get the following IL
for 'PropertyCorrect' (notice the <!T> appended to the type name)
.method public hidebysig specialname instance int32
get_PropertyCorrect() cil managed
{
.maxstack 8
L_0000: ldsfld int32 MyAssembly.A`1<!T>::field
L_0005: ret
}
In order to fix the get method of 'Property', I write the following
bit of cecil code:
var assembly = AssemblyDefinition.ReadAssembly(@"MyAssembly.dll", new
ReaderParameters() { ReadSymbols = true });
var type = assembly.MainModule.Types.FirstOrDefault(t =>
"A`1".Equals(t.Name));
var property = type.Properties[0];
var field = type.Fields[0];
var ilProcessor = property.GetMethod.Body.GetILProcessor();
var ldc0Instr = property.GetMethod.Body.Instructions.FirstOrDefault(i
=> i.OpCode.Code == OpCodes.Ldc_I4_0.Code);
if (ldc0Instr != null)
ilProcessor.Replace(ldc0Instr, ilProcessor.Create(OpCodes.Ldsfld,
field));
assembly.Write(@"MyAssembly.dll", new WriterParameters()
{ WriteSymbols = true });
what I get as a result, when I open up the post-processed assembly in
reflector is
.method public hidebysig specialname instance int32 get_Property() cil
managed
{
.maxstack 8
L_0000: ldsfld int32 MyAssembly.A`1::field
L_0005: ret
}
and when I run PEVerify on that assembly, I get the following error:
Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
[IL]: Error: [I:\Work\dev.scratch\C#\CecilLoadFrom_Issue
\CecilGenerics_Issue\bin
\Release\MyAssembly.dll : MyAssembly.A`1[T]::get_Property][offset
0x00000000]Sys
tem.BadImageFormatException: Fields inside generic classes must be
referenced us
ing MemberRefs, even in the same module as the class. [HRESULT
0x8007000B] - An
attempt was made to load a program with an incorrect format.
1 Error(s) Verifying I:\Work\dev.scratch\C#\CecilLoadFrom_Issue
\CecilGenerics_Is
sue\bin\Release\MyAssembly.dll
I tried creating a FieldReference based on the FieldDefinition i.e.
var fieldRef = new FieldReference(field.Name, field.FieldType)
{ DeclaringType = field.DeclaringType };
ilProcessor.Replace(ldc0Instr, ilProcessor.Create(OpCodes.Ldsfld,
fieldRef));
so that AssemblyWriter.LookupToken (IMetadataTokenProvider provider)
would consider the token as MemberRef but this didn't seem to have any
bearing on the outcome.
Am I doing something wrong or is this not supported?
Help would be greatly appreciated as this is a blocking issue for me.
Sincerely,
Gabriel
--
--
mono-cecil