0

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?

Arne Claassen
  • 14,088
  • 5
  • 67
  • 106

2 Answers2

0

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 ?

Timores
  • 14,439
  • 3
  • 46
  • 46
  • I tried both AppDomain.AssemblyResolve and AppDomain.ReflectionOnlyAssemblyResolve and neither ever fired. I assume it's because it already has a different version loaded. I'll look at whether i can use only LoadFrom. – Arne Claassen Feb 24 '10 at 15:35
  • Turns out it was a matter of using LoadFrom for loading the dependents. My initial tests kept failing but for other reasons. all good now. – Arne Claassen Feb 26 '10 at 06:21
  • On second thought, it makes sense, as there are DLLs loaded by .NET itself, which is done with Load and not LoadFrom. So, the correct suggestion should have been to try and do without LoadFrom – Timores Feb 26 '10 at 06:46
  • The problem with Load was that the other version was already loaded, so somehow Load would not fail but not load it either, but by using LoadFrom it succeeded. I actually fall back on Load if LoadFrom fails (so i can load GAC dependencies). It's just that Load gives me a false positive. – Arne Claassen Mar 03 '10 at 20:06
0

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>
John Stewien
  • 1,046
  • 9
  • 5