Search code examples
c#.netmono.cecil

How to resolve references of a .NET assembly from a .Net Core 3.1 code using Mono.Cecil?


My tool is written in .Net Core 3.1. It uses Mono.Cecil to analyze the given assembly, which targets .NET 4.7.2

Given an AssemblyDefinition object and one of its assembly references, I wish to get the AssemblyDefinition object corresponding to that reference.

Here is an example Watch window content:

Name Value Type
a {SharpTop.DB.DL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} Mono.Cecil.AssemblyDefinition
asmRef {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} Mono.Cecil.AssemblyNameReference

Now I wish to resolve the reference to the actual definition:

var asm = a.MainModule.AssemblyResolver.Resolve(asmRef);

However, when inspecting asm.MainModule.FileName I get C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.12\mscorlib.dll

This is wrong, because the original assembly targets .NET 4.7.2, so it is my understanding that its mscorlib reference should resolve to something like c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll or maybe c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2

My conclusion - I resolve the assembly reference incorrectly. So - what is the correct way?


Solution

  • You probably built the tool in .NET Core, this means Mono.Cecil will think it is core assembly and will resolve assemblies from .NET Core locations rather than the .NET Framework GAC.

    https://github.com/jbevain/cecil/blob/2f1077d7bb3527c3d821cb726a6d762abaea101a/Mono.Cecil/BaseAssemblyResolver.cs#L136

    Solution is to either set the target framework of the tool to .NET Framework or to write your own assembly resolver.

    I think ILSpy can be a good reference of how to implement your own assembly resolver: https://github.com/icsharpcode/ILSpy/blob/aa1906b8f54c78f06d41557214ff5bbff9fb2e26/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

    After further investigation, this is indeed the way to do it. ILSpy's resolver is almost interchangeable with Mono.Cecil.