在C++中加載和卸載DLL是一件很容易的事LoadLibrary和FreeLibrary讓你能夠輕易的在程序中加載DLL然後在任何地方卸載在C#中我們也能使用AssemblyLoadFile實現動態加載DLL但是當你試圖卸載時你會很驚訝的發現Assembly沒有提供任何卸載的方法這是由於托管代碼的自動垃圾回收機制會做這件事情所以C#不提供釋放資源的函數一切由垃圾回收來做
這引發了一個問題用Assembly加載的DLL可能只在程序結束的時候才會被釋放這也意味著在程序運行期間無法更新被加載的DLL而這個功能在某些程序設計時是非常必要的考慮你正在用反射機制寫一個查看DLL中所有函數詳細信息的程序程序提供一個菜單讓用戶可以選擇DLL文件這時就需要讓程序能夠卸載DLL否則一旦用戶重新得到新版本DLL時必須要重新啟動程序重新選擇加載DLL文件這樣的設計是用戶無法忍受的
C#也提供了實現動態卸載DLL的方法通過AppDomain來實現AppDomain是一個獨立執行應用程序的環境當AppDomain被卸載的時候在該環境中的所有資源也將被回收關於AppDomain的詳細資料參考MSDN下面是使用AppDomain實現動態卸載DLL的代碼
using System;
using SystemCollectionsGeneric;
using SystemText;
using SystemThreading;
using SystemReflection;
namespace UnloadDll
{
class Program
{
static void Main(string[] args)
{
string callingDomainName = AppDomainCurrentDomainFriendlyName;//ThreadGetDomain()FriendlyName;
ConsoleWriteLine(callingDomainName);
AppDomain ad = AppDomainCreateDomain(DLL Unload test);
ProxyObject obj = (ProxyObject)adCreateInstanceFromAndUnwrap(@UnloadDllexe UnloadDllProxyObject);
objLoadAssembly();
objInvoke(TestDllClass Test Its a test);
AppDomainUnload(ad);
obj = null;
ConsoleReadLine();
}
}
class ProxyObject : MarshalByRefObject
{
Assembly assembly = null;
public void LoadAssembly()
{
assembly = AssemblyLoadFile(@TestDLLdll);
}
public bool Invoke(string fullClassName string methodName params Object[] args)
{
if(assembly == null)
return false;
Type tp = assemblyGetType(fullClassName);
if (tp == null)
return false;
MethodInfo method = tpGetMethod(methodName);
if (method == null)
return false;
Object obj = ActivatorCreateInstance(tp);
methodInvoke(obj args);
return true;
}
}
}
注意
要想讓一個對象能夠穿過AppDomain邊界必須要繼承MarshalByRefObject類否則無法被其他AppDomain使用
每個線程都有一個默認的AppDomain可以通過ThreadGetDomain()來得到
From:http://tw.wingwit.com/Article/program/net/201311/15263.html