Problem with loading/unloading DLL from a separate appDomain  
Author Message
Teddy79





PostPosted: Visual C# General, Problem with loading/unloading DLL from a separate appDomain Top

Hi,
I want to dynamically loading assembly dll to have an instance of a type in that assembly. The thing is the assembly is updated on demand frequently so I need to unload and then reload the dll. So I load it from a separate domain. First I create a new appDomain using AppDomainSetup with shadow copy enabled:

AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.CachePath = AppDomain.CurrentDomain.BaseDirectory+"\\Shadow";
setup.ApplicationName = "Loading";
setup.ShadowCopyFiles = "true";
setup.ShadowCopyDirectories = AppDomain.CurrentDomain.BaseDirectory;
newDomain = AppDomain.CreateDomain(
"loaderDomain", null, setup);

Then a remoteLoader is created
remoteLoader = (RemoteLoader) newDomain.CreateInstanceAndUnwrap("MyApplication","MyApplication.RemoteLoader");

The purpose of the remoteLoader is to load the assembly and reference to it in the new appDomain. So here's the function in the RemoteLoader class to load the assembly and create a target object:
public MyClass LoadObject(string fileName)
{

Assembly assembly = newDomain.Load(fileName);
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
Object obj = assembly.CreateInstance("DllToBeLoad.MyClass", false, flags, null, new Object[] { }, null, new object[] { });
MyClass myObject = obj as MyClass;
return myObject;
}
The returned object is used in the main app domain.

And whenever the target dll changes, I call AppDomain.Unload(newDomain) and do everything again from the beginning to reload. However, this does not work. It only loads the very first version of dll, can not load the updated dll. It's very strange to me cuz the loading code is totally separated from the main app domain. Any idea Thanks in advance.

Trang


Visual C#9  
 
 
jjjjjjjjjjjamie





PostPosted: Visual C# General, Problem with loading/unloading DLL from a separate appDomain Top

Did you ever find an answer to this
 
 
Peter Ritchie





PostPosted: Visual C# General, Problem with loading/unloading DLL from a separate appDomain Top

If you directly access types from an assembly it will be loaded into the main AppDomain; meaning you can't unload the DLL. Same is true if your DLL uses times from the EXE's assembly.

You have to communicate between the AppDomains only with interfaces, and those interfaces need to be defined in a 3rd assembly. Shawn Farkas of Microsoft has some good material on implementing this sort of thing. For example http://msdn.microsoft.com/msdnmag/issues/05/11/hostingaddins/default.aspx

 
 
CLoUdYvIsIoN





PostPosted: Visual C# General, Problem with loading/unloading DLL from a separate appDomain Top

okay after reading article after article on how to do this... this is now what I have.

a host application containing a "Plugin" class, this class merely contains an instance of "Gateway" a class located in a seperate DLL thats responsible for loading the plugin type from the DLL(Implementing "IPlugin") .. Gateway then contains a property called "Instance" which holds an instance(obviously) of the loaded type. On previous versions of my application I have just resorted to loading all known plugins at start up and allowing he user to just enable or disable each plugin individually, but what I would like is to be able to copy over the plugin dll's with newer versions without having to shut down the application.

this is a chatserver application and this is where it gets a bit tricky. I need the plugin to be able to access methods contained in the IServer and IClient interfaces (and a few others) which are implemented in the host application, all inheriting from "AurALease" which inherits from MarshalByRefObject. my "PluginService" class... in the "LoadPlugin" method is responsible for creating a new instance of the "Plugin" class, creating the new domain, then using the new domain to then create an instance of "Gateway" (serializing issues do not allow me to have "Gateway" inherit "AurALease") gateway then loads the desired assembly, assigns the eported type and creates a new instance. a class "PluginHost"( implementing "IHost") instance is then set to the gateway object to provide access to the IServer and IClient interfaces . the resulting calling convetion for calling methods from within the plugin look as so:

Plugin.Gateway.Instance.MethodName();

and for the plugins to call methods from within the host application (mainly server functions):

Host.Server.MethodName(); (host also has methods to allow a plugin to load/kill a different plugin)

now... even though I have followed many of the procedures for loading and unloading appdomains and assemblies. this still does not work for me... is this because I have too many references to objects contained within the host application and vice versa. or is there really a way for me to do this

(I can provide code samples as necessary)

Sorry for such a dragged out post but I thought it appropriate to endulge you in what I'm doing, with as much detail as possible

Thanks in advance

Ryan

[Edit]

the property in "IPlugin" IHost Host{get;set;} is set by "PluginService" to give the plugin access to the IHost implementation. the plugin is "started" by calling a method called Initialize() where I can then notify chat users that the plugin was loaded successfuly by calling a "Print" method. now after removing the code to set this property and any calls the this object.(currently the only object explicitly referenced) it appears the unload still does not remove the assembly from the default domain... as I said I have read many articles.. and I'm just so close to giving up on the AppDomains all together. it would be great if someone could persuade me to continue lol.



 
 
Peter Ritchie





PostPosted: Visual C# General, Problem with loading/unloading DLL from a separate appDomain Top

In order to ensure you can unload a DLL you have to make sure that the main AppDomain never uses types from the "plug-in" DLLs. For example, If you have a type "PluginTwo.PluginService" in your assembly that implements IPlugin, you must always only reference those plug-in objects via IPlugin, not PluginService. As soon as the type PluginService is in the main code the CLR will automatically pull in the assembly where that type is defined into the main AppDomain. This also means that you cannot have IPlugin defined in either the main assembly or the plugin assemblies, IPlugin must be contained within a third assembly because the assembly and all its references will get pulled into the AppDomain that uses IPlugin.