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

Reply via email to