To describe the problem clearly, let's look at an example first. In this example, WinForm has a button that, when clicked on by the user, loads an already existing assembly and displays the Assembly fullname on the label control of the interface. To reflection slightly familiar with a little bit of friends know that this is very simple thing, just need to use the Assembly.loadfile method to get assembly, and then use the FullName attribute to display, such as the following code:
private void Button1_Click (object sender, EventArgs e) { Assembly Assembly = Assembly.loadfile (@ "c \ TestLib.dll "); Label1. Text = assembly. FullName; }
Of course, the program executes normally, and you will not find any compile-time or runtime errors. However, when you compile the called TestLib.dll before exiting the program, you will find that Visual studio cannot complete the compilation, prompting that the file is being used by other processes.
In fact, our program does not have much to do with this testlib.dll, and our program simply shows the basic information of TestLib.dll. If TestLib.dll is a shared library, resource monopoly issues can affect the normal functioning of other programs.
Assembly does not have unload functionality, but the AppDomain can be used to solve this problem. The basic idea is to create a new AppDomain, load assembly in the new AppDomain, call the methods in it, and then return the results you get. After all the operations are done, call the AppDomain.Unload method to unload the new AppDomain, which also uninstalls the assembly. Note: You cannot return the loaded assembly directly to the current application domain (AppDomain).
First, create a remoteloader, which is used to load the assembly in the newly created AppDomain, and to advertise an attribute so that the fullname of assembly can be obtained by the outside world. RemoteLoader need to inherit from MarshalByRefObject. The code is as follows:
public class Remoteloader:marshalbyrefobject { private Assembly Assembly; public void loadassembly (string fullName) { assembly = Assembly.LoadFrom (FullName); } public string FullName { get {return assembly. FullName; } } }
Second, create a localloader. The function of Localloader is to create a new AppDomain and then call RemoteLoader in this new AppDomain to create assembly through RemoteLoader and get information about assembly. At this point the called assembly is naturally loaded in the new AppDomain. Finally, Localloader also needs to provide a new way to uninstall the AppDomain. The code is as follows:
public class Localloader {private AppDomain AppDomain; Private RemoteLoader RemoteLoader; Public Localloader () {appdomainsetup setup = new AppDomainSetup (); Setup. ApplicationName = "Test"; Setup. ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; Setup. Privatebinpath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "private"); Setup. CachePath = Setup. ApplicationBase; Setup. Shadowcopyfiles = "true"; Setup. Shadowcopydirectories = Setup. ApplicationBase; AppDomain = Appdomain.createdomain ("TestDomain", null, Setup); String name = Assembly.getexecutingassembly (). GetName (). FullName; RemoteLoader = (remoteloader) appdomain.createinstanceandunwrap (name, typeof (RemoteLoader). FullName); } public void loadassembly (string fullName) {remoteloader.loadassembly (fullName); } public void Unload () {AppDomain. Unload (AppDomain); AppDomain = null; } public string FullName {get {return remoteloader.fullname; } } }
private void Button1_Click (object sender, EventArgs e) { Localloader ll = new Localloader (); ll. loadassembly (@ "C:\testlib.dll"); Label1. Text = LL. FullName; ll. Unload (); }
After completing the above modifications, our program will also be able to correctly display the assembly FullName, and, after displaying the assembly information, the program actively uninstalls the new AppDomain, To prevent the testlib.dll of resource monopoly, affecting the operation of other programs.