Hi all. I've been fighting this issue for a few days now. My original goal was to load an assembly dll in a new AppDomain so it can be unloaded, for a plugin system. I am able to load the dll in the new AppDomain I created just fine, however all dependencies are loaded in the parent AppDomain which is pointless as the files remain locked.
Does anyone know if this is actually possible? I've found several others reporting the issue with no resolution:
If you bind to the AssemblyResolve event of the child AppDomain it never gets fired. The AssemblyResolve event only fires on the parent domain and an examination of AppDomain.CurrentDomain.GetAssemblies() confirms the dependencies show up there. (Please note this is stub code, excuse any errors. The actual code uses a Proxy object to instantiate the class on the other AppDomain along with CreateInstanceFromAndUnwrap())
public MyCustomObject BindAssembly() { string currentAssemblyPath = @"C:\PathToMy\Assembly"; string currentAssemblyFile = @"C:\PathToMy\Assembly\MyAssembly.dll"; AssemblyName currentAssemblyName = AssemblyName.GetAssemblyName(currentAssemblyFile); AppDomain domain = AppDomain.CurrentDomain; domain.AssemblyResolve += domain_AssemblyResolve; AppDomainSetup setup = new AppDomainSetup() { PrivateBinPath = currentAssemblyPath, }; AppDomain newDomain = AppDomain.CreateDomain("NewDomain", AppDomain.CurrentDomain.Evidence, setup); newDomain.AssemblyResolve += newDomain_AssemblyResolve; currentAssembly = newDomain.Load(currentAssemblyName); // tried this too //var obj = domain.CreateInstanceFromAndUnwrap(currentAssemblyFile, className); // list all of the assemblies inside the custom app domain var newDomainAssemblies = newDomain.GetAssemblies(); // (contains my loaded assembly, but not dependencies) // list all of the assemblies inside the parent app domain var appAssemblies = AppDomain.CurrentDomain.GetAssemblies(); // (contains my loaded assembly as well as all dependencies) return obj as MyCustomObject; } // resolve dependencies in custom domain Assembly newDomain_AssemblyResolve(object sender, ResolveEventArgs args) { // this never fires AppDomain domain = (AppDomain)sender; } // resolve dependencies in parent domain Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{// always fired for all dependency dll's no matter the AppDomain which loaded it. AppDomain domain = (AppDomain)sender; string assemblyDependencyPath = String.Format(@"{0}", Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(args.RequestingAssembly.CodeBase).Path))); string[] files = Directory.GetFiles(assemblyDependencyPath, "*.dll", SearchOption.AllDirectories); foreach (string file in files) { // if we found it, load the assembly and cache it. AssemblyName aname = AssemblyName.GetAssemblyName(file); if (aname.FullName.Equals(args.Name)) { Assembly assembly = domain.Load(aname); //Assembly assembly = Assembly.LoadFrom(file); // also tried this, same result return assembly; } } }
Michael Brown, 360 Replays Ltd. (don't forget that 'Mark As Answer' button!)