AppDomain與Assembly的動態載入與卸載代碼詳解

來源:互聯網
上載者:User
為了將問題描述清楚,我們先來看一個例子。在這個例子中,WinForm上有一個按鈕,當使用者點擊這個按鈕後,就會裝載一個已經存在的Assembly,並且在介面的Label控制項上顯示出這個Assembly的FullName。對Reflection稍微熟悉一點的朋友都知道,這是非常簡單的事情,只需要用Assembly.LoadFile方法獲得Assembly,然後用FullName屬性來顯示即可,比如下面的代碼:

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



當然,程式執行正常,您不會發現任何編譯時間或運行時的錯誤。然而,當你在沒有退出此程式之前,再去編譯被調用的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。代碼如下:

public class RemoteLoader : MarshalByRefObject  {      private Assembly assembly;      public void LoadAssembly(string fullName)      {          assembly = Assembly.LoadFrom(fullName);      }      public string FullName      {          get { return assembly.FullName; }      }  }



其次,建立一個LocalLoader。LocalLoader的功能是建立新的AppDomain,然後在這個新的AppDomain中調用RemoteLoader,以便通過RemoteLoader來建立assembly並獲得assembly的相關資訊。此時被調用的assembly自然被裝載於新的AppDomain中。最後,LocalLoader還需要提供一個新的方法,就是AppDomain的卸載。代碼如下:

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;          }      }  }


  • 最後,修改我們WinForm上的Button Click事件處理過程,改為如下的形式:

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



在完成上述的修改後,我們的程式也同樣能夠正確地顯示assembly的FullName,而且,在顯示完assembly資訊後,程式會主動卸載建立的AppDomain,以防止testlib.dll的資源獨佔,影響其它程式的運行。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.