• AppDomain与Assembly的加载与卸载


    为了将问题描述清楚,我们先来看一个例子。在这个例子中,WinForm上有一个按钮,当用户点击这个按钮后,就会装载一个已经存在的Assembly,并且在界面的Label控件上显示出这个Assembly的FullName。对Reflection稍微熟悉一点的朋友都知道,这是非常简单的事情,只需要用Assembly.LoadFile方法获得Assembly,然后用FullName属性来显示即可,比如下面的代码:

    1. private void button1_Click(object sender, EventArgs e)  
    2. {  
    3.     Assembly assembly = Assembly.LoadFile(@"C:\testlib.dll");  
    4.     label1.Text = assembly.FullName;  
    5. }  

    当然,程序执行正常,您不会发现任何编译时或运行时的错误。然而,当你在没有退出此程序之前,再去编译被调用的testlib.dll,你会发现,Visual Studio无法完成编译,提示说该文件正在被其它的进程所使用,如下:

    事实上,我们的程序与这个testlib.dll并没有太大的关联,我们的程序只不过就是显示一下testlib.dll的基本信息。如果testlib.dll是一个共享的库,那么资源独占问题会影响到其它程序的正常工作。

    Assembly没有Unload的功能,但可以使用AppDomain来解决这个问题。基本思路是,创建一个新的AppDomain,在这个新建的AppDomain中装载assembly,调用其中的方法,然后将获得的结果返回。在完成所有操作以后,调用AppDomain.Unload方法卸载这个新建的AppDomain,这样也同时卸载了assembly。注意:你无法将装载的assembly直接返回到当前应用程序域(AppDomain)。

    首先,创建一个RemoteLoader,这个RemoteLoader用于在新建的AppDomain中装载assembly,并向外公布一个属性,以便外界能够获得assembly的FullName。RemoteLoader需要继承于MarshalByRefObject。代码如下:

    1. public class RemoteLoader : MarshalByRefObject  
    2. {  
    3.     private Assembly assembly;  
    4.   
    5.     public void LoadAssembly(string fullName)  
    6.     {  
    7.         assembly = Assembly.LoadFrom(fullName);  
    8.     }  
    9.   
    10.     public string FullName  
    11.     {  
    12.         get { return assembly.FullName; }  
    13.     }  
    14. }  

    其次,创建一个LocalLoader。LocalLoader的功能是创建新的AppDomain,然后在这个新的AppDomain中调用RemoteLoader,以便通过RemoteLoader来创建assembly并获得assembly的相关信息。此时被调用的assembly自然被装载于新的AppDomain中。最后,LocalLoader还需要提供一个新的方法,就是AppDomain的卸载。代码如下:

    1. public class LocalLoader  
    2. {  
    3.     private AppDomain appDomain;  
    4.     private RemoteLoader remoteLoader;  
    5.   
    6.     public LocalLoader()  
    7.     {  
    8.         AppDomainSetup setup = new AppDomainSetup();  
    9.         setup.ApplicationName = "Test";  
    10.         setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;  
    11.         setup.PrivateBinPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "private");  
    12.         setup.CachePath = setup.ApplicationBase;  
    13.         setup.ShadowCopyFiles = "true";  
    14.         setup.ShadowCopyDirectories = setup.ApplicationBase;  
    15.   
    16.         appDomain = AppDomain.CreateDomain("TestDomain"null, setup);  
    17.         string name = Assembly.GetExecutingAssembly().GetName().FullName;  
    18.         remoteLoader = (RemoteLoader)appDomain.CreateInstanceAndUnwrap(  
    19.             name,  
    20.             typeof(RemoteLoader).FullName);  
    21.     }  
    22.   
    23.     public void LoadAssembly(string fullName)  
    24.     {  
    25.         remoteLoader.LoadAssembly(fullName);  
    26.     }  
    27.   
    28.     public void Unload()  
    29.     {  
    30.         AppDomain.Unload(appDomain);  
    31.         appDomain = null;  
    32.     }  
    33.   
    34.     public string FullName  
    35.     {  
    36.         get  
    37.         {  
    38.             return remoteLoader.FullName;  
    39.         }  
    40.     }  
    41. }  

    最后,修改我们WinForm上的Button Click事件处理过程,改为如下的形式:

    1. private void button1_Click(object sender, EventArgs e)  
    2. {  
    3.     LocalLoader ll = new LocalLoader();  
    4.     ll.LoadAssembly(@"C:\testlib.dll");  
    5.     label1.Text = ll.FullName;  
    6.     ll.Unload();  
    7. }  

    在完成上述的修改后,我们的程序也同样能够正确地显示assembly的FullName,而且,在显示完assembly信息后,程序会主动卸载新建的AppDomain,以防止testlib.dll的资源独占,影响其它程序的运行。

  • 相关阅读:
    【最短路】BAPC2014 B Button Bashing (Codeforces GYM 100526)
    【链表】【模拟】Codeforces 706E Working routine
    【数论】【扩展欧几里得】Codeforces 710D Two Arithmetic Progressions
    【动态规划】【最短路】Codeforces 710E Generate a String
    【模拟】Codeforces 710C Magic Odd Square
    【模拟】Codeforces 710B Optimal Point on a Line
    【模拟】Codeforces 710A King Moves
    【模拟】Codeforces 705A Hulk
    【模拟】Codeforces 705B Spider Man
    【模拟】Codeforces 704A & 705C Thor
  • 原文地址:https://www.cnblogs.com/daxnet/p/1686999.html
Copyright © 2020-2023  润新知