程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> C#中動態加載和卸載DLL

C#中動態加載和卸載DLL

編輯:C#基礎知識

  在C++中加載和卸載DLL是一件很容易的事,LoadLibrary和FreeLibrary讓你能夠輕易的在程序中加載DLL,然後在任何地方 卸載。在C#中我們也能使用Assembly.LoadFile實現動態加載DLL,但是當你試圖卸載時,你會很驚訝的發現Assembly沒有提供任何 卸載的方法。這是由於托管代碼的自動垃圾回收機制會做這件事情,所以C#不提供釋放資源的函數,一切由垃圾回收來做。 
  這引發了一個問題,用Assembly加載的DLL可能只在程序結束的時候才會被釋放,這也意味著在程序運行期間無法更新被加載的DLL。而這個功能在某 些程序設計時是非常必要的,考慮你正在用反射機制寫一個查看DLL中所有函數詳細信息的程序,程序提供一個菜單讓用戶可以選擇DLL文件,這時就需要讓程 序能夠卸載DLL,否則一旦用戶重新得到新版本DLL時,必須要重新啟動程序,重新選擇加載DLL文件,這樣的設計是用戶無法忍受的。 
  C#也提供了實現動態卸載DLL的方法,通過AppDomain來實現。AppDomain是一個獨立執行應用程序的環境,當AppDomain被卸載的 時候,在該環境中的所有資源也將被回收。關於AppDomain的詳細資料參考MSDN。下面是使用AppDomain實現動態卸載DLL的代碼:

 using System; 
 using System.Collections.Generic; 
 using System.Text; 
 using System.Threading; 
 using System.Reflection; 
 namespace UnloadDll 
 { 
 class Program 
 { 
 static void Main(string[] args) 
 { 
 string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName; 
 Console.WriteLine(callingDomainName); 
 AppDomain ad = AppDomain.CreateDomain("DLL Unload test"); 
 ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe", "UnloadDll.ProxyObject"); 
 obj.LoadAssembly(); 
 obj.Invoke("TestDll.Class1", "Test", "It's a test"); 
 AppDomain.Unload(ad); 
 obj = null; 
 Console.ReadLine(); 
 } 
 } 
 class ProxyObject : MarshalByRefObject 
 { 
 Assembly assembly = null; 
 public void LoadAssembly() 
 { 
 assembly = Assembly.LoadFile(@"TestDLL.dll"); 
 } 
 public bool Invoke(string fullClassName, string methodName, params Object[] args) 
 { 
 if(assembly == null) 
 return false; 
 Type tp = assembly.GetType(fullClassName); 
 if (tp == null) 
 return false; 
 MethodInfo method = tp.GetMethod(methodName); 
 if (method == null) 
 return false; 
 Object obj = Activator.CreateInstance(tp); 
 method.Invoke(obj, args); 
 return true; 
 } 
 } 
 } 

注意: 

1. 要想讓一個對象能夠穿過AppDomain邊界,必須要繼承MarshalByRefObject類,否則無法被其他AppDomain使用。 

2. 每個線程都有一個默認的AppDomain,可以通過Thread.GetDomain()來得到。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved