views:

4952

answers:

3

I want to load to new AppDomin some assembly which has a complex references tree (MyDll.dll -> Microsoft.Office.Interop.Excel.dll -> Microsoft.Vbe.Interop.dll -> Office.dll -> stdole.dll)

As far as I understood, when an assembly is been loaded to AppDomain, it's references would not be loaded automatically, and I have to load them manually. So when I do:

string dir = @"SomePath"; // different from AppDomain.CurrentDomain.BaseDirectory
string path = System.IO.Path.Combine(dir, "MyDll.dll");

AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
setup.ApplicationBase = dir;
AppDomain domain = AppDomain.CreateDomain("SomeAppDomain", null, setup);

domain.Load(AssemblyName.GetAssemblyName(path));

and got FileNotFoundException:

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

I think the key word is one of its dependencies.

Ok, I do next before domain.Load(AssemblyName.GetAssemblyName(path));

foreach (AssemblyName refAsmName in Assembly.ReflectionOnlyLoadFrom(path).GetReferencedAssemblies())
{
    domain.Load(refAsmName);
}

But got FileNotFoundException again, on another (referenced) assembly.

How to load all references recursively?

Have I to create references tree before loading root assembly? How to get an assembly's references without loading it?

+1  A: 

You need to handle the AppDomain.AssemblyResolve or AppDomain.ReflectionOnlyAssemblyResolve events (depending on which load you're doing) in case the referenced assembly is not in the GAC or on the CLR's probing path.

AppDomain.AssemblyResolve

AppDomain.ReflectionOnlyAssemblyResolve

Dustin Campbell
So I have to indicate requested assembly manually? Even it is in new AppDomain's AppBase ? Is there a way not to do that?
abatishchev
+1  A: 

On your new AppDomain, try setting an AssemblyResolve event handler. That event gets called when a dependency is missing.

David
+1  A: 

http://support.microsoft.com/kb/837908/en-us

C# version

Create a moderator class and inherit it from MarsharByRef

class ProxyDomain : MarshalByRefObject
{
    public Assembly GetAssembly(string AssemblyPath)
    {
        try
        {
            return Assembly.LoadFrom(AssemblyPath);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(ex);
        }
    }
}

call from client site

ProxyDomain pd = new ProxyDomain();
Assembly assembly = pd.GetAssembly(assemblyFilePath);