-
-
Notifications
You must be signed in to change notification settings - Fork 638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type resolution depends on the program that is running, not the assembly being processed. #863
Comments
@SteveGilham how are you resolving types? |
The simple example provided is using the The issue was originally observed (SteveGilham/altcover#156) in a context using a .net core executable that added a |
you need to implement your own AssemblyResolver that respects the runtime of the target assembly. Cecil cannot do this for you. for example here is the AssemblyResolver in fody https://github.com/Fody/Fody/blob/master/FodyIsolated/AssemblyResolver.cs that uses the msbuild context to resolve assemblies |
That's why I'm making this issue report. It could and should avoid such platform-inconsistent behaviour, and can do it simply by changing the compile-time logic check to being a run-time one. |
PR #864 does the core of the work, sufficient to let one write an assembly resolver that sub-classes e.g. Going on from here, there are possibilities such as dropping the remaining #if block in favour of a strategy pattern, with the default strategy being chosen at compile time as now, and making the selection at run time available. That could build into the initialization of the default resolver (in |
Is there no chicken/egg issue with trying to have the behaviour of the resolver depend on |
You can get the attribute type name and examine the associated binary blob data w/o any resolver as the following example demonstrates using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace CecilGAC
{
public class NonResolver : IAssemblyResolver
{
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
throw new NotImplementedException();
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
throw new NotImplementedException();
}
public void Dispose()
{
}
}
internal class Program
{
private static void Main(string[] args)
{
var parameters = new ReaderParameters();
parameters.AssemblyResolver = new NonResolver();
var def = AssemblyDefinition.ReadAssembly([assembly path goes here], parameters);
foreach (var a in def.CustomAttributes)
{
Console.WriteLine(a.AttributeType.FullName);
var b = a.GetBlob();
var s = System.Text.Encoding.ASCII.GetString(b);
Console.WriteLine(s);
}
}
}
} |
An assembly built to target the .Net Framework expects to resolve system references in the GAC; however a .net (core) program using Cecil to manipulate that assembly resolves them to the trusted locations under dotnet/shared. The two files will not always match up.
Here's an example --
ClassLibrary.csproj
builds a WPF-consuming assembly that referencesWindowsBase.dll
v4.0.0.0 in the GAC.CecilGAC.csproj
is a simple .net6.0 program that reads and rewrites theClassLibrary1.dll
assembly.CecilGAC.zip
The program fails during write with
because a
WindowsBase.dll
v4.0.0.0 has been found withinC:\Program Files\dotnet\shared\Microsoft.NETCore.App
; but that assembly is a stub containing onlyHowever, if
CecilGAC.csproj
is modified to bebuilding against .Net Framework v4.8, the write operation finds the expected file in the GAC, and the type resolution completes successfully.
Because a suitable strong-named assembly has been found in the ,net core case, a simple reactive approach such as overriding the AssemblyResolver to handle resolution failures by checking the GAC (if present) does not resolve the issue; the necessary fix would be to replace the
#if NET_CORE
compile-time logic with a runtime selection based on the[TargetFramework]
attribute value of the assembly being manipulated.[ADDED] An alternative would be to recognise such a pure stub assembly and consider it an assembly resolution failure; this form of stub seems to be a standard pattern for GUI-related assemblies.
The text was updated successfully, but these errors were encountered: