Unloading a domain doesnt release .DLL files

Aug 20, 2014 at 3:47 AM
Edited Aug 20, 2014 at 3:51 AM
Hello,

Im trying to use ProcessDomain to allow me to hot-swap assemblies. Bascially it was my impression, that having process level isolation will facilitate this.

/host.dll

apps/1.0/plugin.dll
 private IUpdateble LoadApp(Type component)
        {
            var root = new FileInfo(component.Assembly.Location);
            var domain = ProcessDomain.CreateDomain(String.Format("Hosted_{0}", component.AssemblyQualifiedName), new ProcessDomainSetup()
            {
                CompilerVersion = "v4.0",
                AppDomainSetupInformation = new AppDomainSetup()
                {
                    ConfigurationFile = root.Name + ".config",
                    ApplicationBase = root.DirectoryName
                }
            });

            var app = domain.CreateInstanceAndUnwrap(component.Assembly.FullName, component.FullName) as IUpdateble;
            
            if (app == null)
                throw new InvalidOperationException("App must implement IUpdatable to use with loader");

            domain.Attached += () => Console.WriteLine("Process loaded");
            domain.Detached += () => Console.WriteLine("Process unloaded");
            
            Apps.Add(domain, app);

            return app;
        }
            
...
ProcessDomain.Unload(app.Key);
My IUpdatable implementation derives from MarshalByRefObject. My host has no direct reference to the object.
The app loads and runs successfully, but when I unload it, the .dlls are not released. I thought i would pose the question before i go trawling the source for a solution.
Coordinator
Aug 20, 2014 at 2:21 PM
Can you be a little more specific as to what DLL is loaded into what process?

Also, how is the 'component' parameter being acquired and passed in? If you're doing something like Type.GetType("MyComponent, MyAssembly"), then MyAssembly will be necessarily loaded into the current process in order to resolve type information. If you do Type.ReflectionOnlyGetType("MyComponent, MyAssembly"), then the assembly will only get loaded into the reflection-only context. In general, if you want to avoid having the assembly get loaded into the parent process, you must use just strings for the names, or, optionally, AssemblyName for the assembly. This is also the reason why CreateInstanceAndUnwrap uses only strings.
Aug 21, 2014 at 1:12 AM
Edited Aug 21, 2014 at 1:22 AM
eternal0,

Thanks. you hit the nail on the head! I was loading everything with strings but just realized I was doing an Assembly.LoadFrom when inspecting the types looking for classes which implemented IUpdatable- which is defined in the calling assembly, not the plugin, so everything else is decoupled. Glad to know that this should be possible. I'll post up my results when i get some time to refactor.
Sep 16, 2014 at 7:09 AM
Just wanted to confirm that this approach works.
Coordinator
Sep 17, 2014 at 6:48 PM
Cool, good to know, let me know if you have any other questions