AppDomain dependencies across directories
Posted
by
strager
on Stack Overflow
See other posts from Stack Overflow
or by strager
Published on 2010-12-24T14:31:29Z
Indexed on
2010/12/24
15:54 UTC
Read the original article
Hit count: 609
I am creating a plugin system and I am creating one AppDomain per plugin. Each plugin has its own directory with its main assemblies and references. The main assemblies will be loaded by my plugin loader, in addition to my interface assemblies (so the plugin can interact with the application).
Creating the AppDomain:
this.appDomain = AppDomain.CreateDomain("AppDomain", null, new AppDomainSetup
{
ApplicationBase = pluginPath,
PrivateBinPath = pluginPath,
});
Loading the assemblies:
this.appDomain.Load(myInterfaceAssembly.GetName(true));
var assemblies = new List<Assembly>();
foreach (var assemblyName in this.assemblyNames)
{
assemblies.Add(this.appDomain.Load(assemblyName));
}
The format of assemblyName is the assembly's filename without ".dll".
The problem is that AppDomain.Load(assemblyName) throws an exception:
Could not load file or assembly '[[assemblyName]], Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
All of the dependencies of [[assemblyName]] are:
- Inside the directory
pluginPath, - The
myInterfaceAssemblywhich is already loaded, or - In the GAC (e.g. mscorelib).
Clearly I'm not doing something right. I have tried:
- Creating an object using
this.appDomain.CreateInstanceAndUnwrapinheriting from MarshalByRefObject with aLoadAssemblymethod to load the assembly. I get an exception saying that the current assembly (containing the proxy class) could not be loaded (file not found, as above), even if I manually callthis.appDomain.Load(Assembly.GetExecutingAssembly().GetName(true)). - Attaching an
AssemblyResolvehandler tothis.appDomain. I'm met with the same exception as in (1), and manually loading doesn't help. Recursively loading assemblies by loading their dependencies into
this.appDomainfirst. This doesn't work, but I doubt my code is correct:private static void LoadAssemblyInto(AssemblyName assemblyName, AppDomain appDomain) { var assembly = Assembly.Load(assemblyName); foreach (var referenceName in assembly.GetReferencedAssemblies()) { if (!referenceName.FullName.StartsWith("MyProject")) { continue; } var loadedAssemblies = appDomain.GetAssemblies(); if (loadedAssemblies.Any((asm) => asm.FullName == referenceName.FullName)) { continue; } LoadAssemblyInto(referenceName, appDomain); } appDomain.Load(assembly.GetName(true)); }
How can I load my plugin assembly with its dependencies in that plugin's directory while also loading some assemblies in the current directory?
Note: The assemblies a plugin may (probably will) reference are already loaded in the current domain. This can be shared across domains (performance benefit? simplicity?) if required.
Fusion log:
*** Assembly Binder Log Entry (12/24/2010 @ 10:46:40 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
LOG: Start binding of native image vshost32, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86.
WRN: No matching native image found.
LOG: Bind to native image assembly did not succeed. Use IL image.
LOG: IL assembly loaded from C:\MyProject\bin\Debug\MyProject.vshost.exe
© Stack Overflow or respective owner