Cannot reflect over assembly that shares a dependency of different version

1.1k Views Asked by At

Here's the scenario using Assembly.ReflectionOnlyLoadFrom:

Both my assembly Inspected and my reflection Application Inspector reference Assembly Dependency.

If Inspector references Dependency 1.0.0.0 and Inspected references Dependency 1.1.0.0, Inspector cannot reflect over any types or methods in Inspected that use a type from Dependency. The moment such a type is hit i get:

System.IO.FileLoadException: Could not load file or assembly 'Dependency, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

However, Inspector can reflect over Dependency 1.1.0.0 itself just fine, so loading Dependency 1.1.0.0 as Assembly.ReflectionOnlyLoadFrom does work from an assembly that's already using Dependency 1.0.0.0.

Here is the code i use to load an assembly and preload it's dependencies:

var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
foreach (var assemblyName in assembly.GetReferencedAssemblies()) {
  Assembly.ReflectionOnlyLoad(assemblyName.FullName);
}

It's not an issue with Dependency 1.1.0.0 not being resolved, as i've set a breakpoint in the foreach and confirmed it is loaded and also checked AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies() for its presence. It's loaded alright. But when i then do assembly.GetTypes(), it dies.

Is there something i can do about this, or do i have to reflect over assemblies in a separate AppDomain and marshall the meta data back into the appdomain that has a reference to Dependency 1.0.0.0?

2

There are 2 best solutions below

4
On BEST ANSWER

In Customizing the .NET Framework Common Language Runtime , it is explained that Load and LoadFrom create separate "scopes" for loaded assemblies, which I guess explains the problem. Something to try is to find the assemblies yourself and load them all with LoadFrom.

Have you tried handling the AppDomain.AssemblyResolve event ?

0
On

I just hit this problem 11 years after the original question. Solved it by applying the current AppDomain policy to the assembly being loaded by reflection:

Assembly.ReflectionOnlyLoad(AppDomain.CurrentDomain.ApplyPolicy(args.Name));

Note in the app.config for the running application you will need a redirect like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Some.Dependency" publicKeyToken="someToken" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>