Question

I have an application with the following folder structure:

Application\Modules\XXX

Of course any assembly inside XXX finds other assemblies inside the XXX.

The problem happens with some instances that are instantiated used reflection:

TProvider providerInstance = (TProvider)Activator.CreateInstance(providerType));

TProvider has a method that returns a class defined in another assembly (stored in XXX as well). When calling that method of the providerInstance that has to load a reference I'm getting a FileNotFoundException about not finding the dependent assembly even when the dependency is in the same XXX folder.

Looking at the fusion log the assembly loader is only checking on the Application folder, not the XXX ...

Any idea on why this happens and how to fix it?

Thanks.

Was it helpful?

Solution

The reason is in that you're loading assembly with LoadFile method:

LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does.

You should use LoadFrom method and load-from context, or, better, if it is possible, use Load and load context.

OTHER TIPS

I'm loading them with Assembly.LoadFile(filename)

That's a very common mistake. It is often made because only LoadFile() has a decent MSDN article that doesn't read like gobbledegook, loading contexts are a very abstract concept in .NET.

LoadFile() should only ever be used if you intentionally don't want dependent assemblies to be found. Which is quite rare, only programs that do things like inspect assemblies would do so. Tools like disassemblers.

LoadFrom() is required to get the CLR to also look in that directory for dependent assemblies. In general beware that this isn't a guaranteed fix for DLL Hell, the identity of a type includes the assembly it came from. Things go wrong with a type with the same namespace name and type name exists in more than one assembly. A failure mode that gets more likely with groups of assemblies in a separate directory. Especially when you don't control its content, like a plug-in scenario. Mystifying InvalidCastExceptions may be your next nemesis, also a very common failure mode for assemblies loaded with LoadFile(). Programmers like to organize files into directories, a bit of OCD that's a professional liability and pretty incompatible with the way the CLR likes to avoid DLL Hell. If this is a requirement for a plug-in scenario then do favor an well worn plug-in framework like MEF to limit the mishaps.

To instruct the CLR to probe under the Modules\XXX subdirectory, create a new configuration file named applicationname.exe.config using any text editor or use the supplied App.config file, and save the file in the folder containing the applicationname.exe application, which, in this example is Application.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Modules\XXX"/>
    </assemblyBinding>
  </runtime>
</configuration>

say you want to specify an assembly using absolute path or relative one (not in same directory hierarchy as the .exe) , use <codebase> instead, anyway these two approaches are bound to the usage of xml configuration files.

Assembly.LoadFrom(...)

Is indeed <codebase> equivalent; can take both relative and absolute paths

main reference: Pro C# 5.0 and .net 4.5

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top