Fody/InfoOf

Field in generic type bug

jasonwoods-7 opened this issue · 1 comments

You should already be a Patron

I am a Patron.

Describe the issue

Using Fody 6.2.0 & InfoOf.Fody 1.6.1, the following code

var info = Info.OfField<List<int>>("_version");

produces this exception

Member 'System.Int32 System.Collections.Generic.List`1<T>::_version' is declared in another module and needs to be imported
   at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
   at Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
   at Mono.Cecil.Cil.CodeWriter.WriteInstructions()
   at Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method)
   at Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddTypes()
   at Mono.Cecil.MetadataBuilder.BuildTypes()
   at Mono.Cecil.MetadataBuilder.BuildModule()
   at Mono.Cecil.MetadataBuilder.BuildMetadata()
   at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
   at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
   at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
   at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   at Fody.WeaverTestHelper.ExecuteTestRun(BaseModuleWeaver weaver, String assemblyPath, Boolean runPeVerify, Action`1 afterExecuteCallback, Action`1 beforeExecuteCallback, String assemblyName, IEnumerable`1 ignoreCodes, Boolean writeSymbols) in C:\projects\fody\FodyHelpers\Testing\WeaverTestHelper.cs:line 90
   at IntegrationTests..cctor() in R:\home\jwoods\src\git\InfoOf\Tests\IntegrationTests.cs:line 21

Minimal Repro

I have added a unit test in a fork of this project at jasonwoods-7/InfoOf

Make an effort to fix the bug

I've done some work trying to get a fix, but don't have a solution.

I'm pretty sure an ImportReference call needs to be added into the OfFieldHandler.cs file after this line.

The best I've managed to do was to add this code

var declaringRef = ModuleDefinition.ImportReference(declaringType.Resolve());
fieldReference = ModuleDefinition.ImportReference(fieldReference, declaringRef);

after the line, but doing this generates this IL

IL_0001: ldtoken field int32 class [mscorlib]System.Collections.Generic.List`1<!0>::_version
IL_0006: ldtoken class [mscorlib]System.Collections.Generic.List`1<int32>
IL_000b: call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle)

instead of the expected

IL_0001: ldtoken field int32 class [mscorlib]System.Collections.Generic.List`1<!T>::_version
IL_0006: ldtoken class [mscorlib]System.Collections.Generic.List`1<int32>
IL_000b: call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle)

Doing this at least gets past the Member 'System.Int32 System.Collections.Generic.List``1<T>::_version' is declared in another module and needs to be imported error, but the <!0> vs <!T> in the ldtoken instruction throws System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) when running the unit test.

I just wanted to raise this issue just in case you know of some way to correctly use Mono.Cecil to import the reference to the field.

I'll continue to look into this issue when I have more free time and I'll submit a PR if I can find a fix.

This is now deployed. NuGet may take some time to make it available for download.