Skip to content

Type resolution depends on the program that is running, not the assembly being processed. #863

@SteveGilham

Description

@SteveGilham

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 references WindowsBase.dll v4.0.0.0 in the GAC. CecilGAC.csproj is a simple .net6.0 program that reads and rewrites the ClassLibrary1.dll assembly.

CecilGAC.zip

The program fails during write with

Mono.Cecil.ResolutionException: Failed to resolve System.Windows.Threading.DispatcherPriority
at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
...

because a WindowsBase.dll v4.0.0.0 has been found within C:\Program Files\dotnet\shared\Microsoft.NETCore.App; but that assembly is a stub containing only

internal class <Module>
{
}

However, if CecilGAC.csproj is modified to be

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net48" Version="1.0.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Mono.Cecil" Version="0.11.4" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
  </ItemGroup>

</Project>

building 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions