Load assemblies with dependencies in a different AppDomain

8.3k views Asked by At

My aim is to make a missing dependency check between 2 given folders. Imagine the following setup.

Root\DirA\A.dll

Root\DirB\B.dll

B depends on A.

So given these folders, I want to create a new AppDomain, load B.dll and have the dependency from DirA(A.dll) automatically resolved and isolated in that new AppDomain.

Isolation is key here given that when I unload this AppDomain I want to create a new one with potentially DirA as a dependency again but DirC libraries that require it so in the case that DirC has a dependency on DirB as well I want it to throw an exception.

Edit: Adding a code example in case that it helps describe my question better.

AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = @"C:\Root";
setup.ApplicationName = "Isolated Domain"
setup.PrivateBinPath = @"DirA;DirB";
setup.PrivateBinPathProbe = "";//disable search in AppBase..
var domain = AppDomain.CreateDomain(Guid.NewGuid().ToString(),
                                    AppDomain.CurrentDomain.Evidence,
                                    setup,
                                    AppDomain.CurrentDomain.PermissionSet);
//The following statement in theory should pick B.dll's dependency from DirA.
var assembly = domain.Load(AssemblyName.GetAssemblyName(@"C:\Root\DirB\B.dll").Name);
//Do the same in a different domain for C.dll

Thanks for any help on that.

2

There are 2 answers

1
Oblivion2000 On

AppDomain's cannot probe for dll's outside of their initial folder. They can probe in the GAC, and in the PrivateBinPath deeper into the folder, but they cannot probe into other folders.

5
paquetp On

This looks like a job for the ResolveEventHandler (more detail on MSDN regarding resolving unknown assemblies)

So, you can write something like

class MyResolver
{
  public static Assembly MyResolveEventHandler( Object sender, ResolveEventArgs args )
  {
    // confirm args.Name contains A.dll
    String dllName = args.Name.Split({','}, SplitStringOptions.None)[0];
    if (dllName == "A")
    {
      return Assembly.LoadFile(@"C:\Root\DirA\A.dll")
    }
    return null;
  }
}

and in the domain you created, you'd do a:

domain.AssemblyResolve += new ResolveEventHandler(MyResolver.MyResolveEventHandler);

Make sure you bind the event before you reference A in B.