幾年前寫過同名隨筆,但今天應不大適用了。但還有幾個朋友留言關注,我重新發布相關代碼。
首先我們的目的就是運行期間更新dll,並應用dll。這個過程需要應用 AppDomain來解決,辦法就是創建新的AppDomain加載dll,並在dll更新後創建新的AppDomain來加載新的dll。
好了,我們有兩個目錄需要完成。
第一個目標:運行時能更新dll。
1.創建AppDomain時設置ShadowCopyFiles
AppDomainSetup _setup = new AppDomainSetup();
_setup.ShadowCopyFiles = "true";
_setup.LoaderOptimization = LoaderOptimization.SingleDomain;
AppDomain _curDomain = AppDomain.CreateDomain("TestDomain", null, _setup);
2.當我們的主程序需要引用動態加載dll中的某個對象的實例時,該實例必須創建爲代理類。代理類的意思是類需要繼承自MarshalByRefObject。此外一般會使用另一個公共類庫定義基類或接口來使用這個代理類。好了,先看怎麼樣在前面創建的程序域中創建代理類的實例
System.Runtime.Remoting.ObjectHandle objHandle = pJobDomain.CreateInstanceFrom(strDllFilePath, strClassName);
object objBuild = objHandle.Unwrap();
if (objBuild == null)
throw new Exception("buildWorker -- 創建對象失敗");
else
ido = (IDo)objBuild;//IDo是一個接口
好了,如果strDllFilePath=“ClassLibrary.dll”,那麼運行目錄的ClassLibrary.dll文件被加載後,我們還是可以隨便更新他的。但更新後,程序域不重新創建的話,使用上面的方法再次創建代理實例,我們的程序依然看不到新的dll的運行效果的,因爲我們加載時設置了ShadowCopyFiles="true"。當然你可能會說設置爲"false"行不行呢?你可以試試,但我要說的是,如果這樣的話,我們第一個目標都完成不了。
第二個目標:應用新的dll。
其實很簡單,UnLoad後再創建一次,使用新的AppDomain創建代理類 ,程序就能看到新dll的效果。好,我定義了一個方法保證每運行一次都會創建一個新的程序域
AppDomain _curDomain;
private void load()
{
if (_curDomain != null)//已創建了程序域
{
AppDomain.Unload(_curDomain);//先關閉再打開。
_curDomain = null;
}
AppDomainSetup _setup = new AppDomainSetup();
_setup.ShadowCopyFiles = "true";
_setup.LoaderOptimization = LoaderOptimization.SingleDomain;
_curDomain = AppDomain.CreateDomain("TestDomain", null, _setup);
}
提供一個kevin-y的測試的源代碼 給大家下載