views:

229

answers:

2

There are several questions out there that ask the same question. However the answers they received I cannot understand, so here goes:

Similar questions:
http://stackoverflow.com/questions/1874277/dynamically-load-assembly-and-manually-force-path-to-get-referenced-assemblies ;
http://stackoverflow.com/questions/22012/loading-assemblies-and-its-dependencies-closed

The question in short: I need to figure out how dependencies, ie References in my modules can be loaded dynamically. Right now I am getting "The system cannot find the file specified" on Assemblies referenced in my so called modules.

I cannot really get how to use the AssemblyResolve event...

The longer version

I have one application, MODULECONTROLLER, that loads separate modules.

These "separate modules" are located in well-known subdirectories, like

appBinDir\Modules\Module1
appBinDir\Modules\Module2

Each directory contains all the DLLs that exists in the bin-directory of those projects after a build.

So the MODULECONTROLLER loads all the DLLs contained in those folders using this code:

byte[] bytes = File.ReadAllBytes(dllFileFullPath);
Assembly assembly = null;
assembly = Assembly.Load(bytes);

I am, as you can see, loading the byte[]-array (so I dont lock the DLL-files).

Now, in for example MODULE1, I have a static reference called MyGreatXmlProtocol. The MyGreatXmlProtocol.dll then also exists in the directory appBinDir\Modules\Module1 and is loaded using the above code

When code in the MODULE1 tries to use this MyGreatXmlProtocol, I get:

Could not load file or assembly 'MyGreatXmlProtocol, Version=1.0.3797.26527, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

So, in a post (like this one) they say that

To my understanding reflection will load the main assembly and then search the GAC for the referenced assemblies, if it cannot find it there, you can then incorparate an assemblyResolve event:

First; is it really needed to use the AssemblyResolve-event to make this work? Shouldnt my different MODULEs themself load their DLLs, as they are statically referenced?

Second; if AssemblyResolve is the way to go - how do I use it? I have attached a handler to the Event but I never get anything on MyGreatXmlProctol...

=== EDIT === CODE regarding the AssemblyResolve-event handler:

public GUI()
{
    InitializeComponent();

    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    ...
}

// 
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    Console.WriteLine(args.Name);
    return null;
}

Hope I wasnt too fuzzy =)

Thx

A: 

try to do assembly = Assembly.Load(bytes); to MyGreatXmlProtocol assembly. I read somewhere that if you load assembly by byte array you have to resolve dependencies manually.

Andrey
yes, that is done. I tried to explain that in my post:"The MyGreatXmlProtocol.dll then also exists in the directory appBinDir\Modules\Module1 and is loaded using the above code"
Ted
@Ted: so you say that error happens despite of loading?
Andrey
Yes, it does. I am sure that the MyGreatXmlProtocol.dll is loaded, I have breaked the app and "seen it happen". Also, this prints i den output: "'ModuleController.vshost.exe' (Managed): Loaded 'MyGreatXmlProtocol'"
Ted
A: 

I would try using Assembly Load or LoadFrom instead. You can enable shadow copying on your AppDomain to make sure it does not lock the loaded dll's (http://blogs.msdn.com/b/junfeng/archive/2004/02/09/69919.aspx). I also found some information about how you should implement AssemblyResolve (http://support.microsoft.com/kb/837908). Secondly you should also check out the RelativeSearchPath property on the AppDomain which tells fusion where to resolve your private assemblies (http://msdn.microsoft.com/en-us/library/system.appdomain.relativesearchpath%28v=VS.100%29.aspx).

Marius