我與很多人都在找這問題的答案。還好,我很幸運,沒有進入很多人都進入的死衚衕而漫長的討論中。因爲我找到了這篇文章
黃天不負有心人,終於全身而退,哈哈
文章說得很明白,我去掉其他設置,只使用以下代碼時
AppDomain.CurrentDomain.SetShadowCopyFiles();
在文章發佈的幾天後,我在微軟的MSDN上發現了這文章。似乎闡述得更爲系統
http://www.microsoft.com/china/msdn/library/langtool/vcsharp/csharp05162002.mspx
在加載dll時有一個奇怪現象,以下代碼會報錯
於是使用以下代碼
object objBuild = asm.CreateInstance(str[0]);
if(objBuild==null)
Mag.Windows.Interface.Log.AddErr("buildWorker","創建對象失敗");
else
iDo = (Mag.Windows.Interface.IDo)objBuild;
上面的代碼還有一個問題,就是我UnLoad程序域後,重新編譯dll,也看到dll成功更新了。應用程序域檢測到配置被修改後,重新使用上面的代碼載入dll,但程序結果並不是我期待的!!程序行爲還是上面版本dll的。估計是使用了緩存的dll。嘗試換用以下代碼
object objBuild = objHandle.Unwrap();
設置SetShadowCopyFiles後,程序運行期間,程序文件是可以隨意更新的,不過不會應用這些變化,除非重新啓動程序。不過在我的項目中這個不是問題。因爲主程序是極小去更新的,但相關的dll就需要不斷的修正,並重新加載到程序域中。所以上文的提示已很足夠了。以下是我的代碼
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.ShadowCopyDirectories = "true";
//主程序很少更新,可以不設置,但考慮還要有可能,
//設置後,更新完文件直接通知網管重啓就可以了。不需要先關再上傳文件,再通知開啓這麼麻煩
AppDomain.CurrentDomain.SetShadowCopyFiles();
//新域的 config 和本域公用一個。不使用默認的配置文件。
// setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
//安全級別相同
System.Security.Policy.Evidence adevidence = AppDomain.CurrentDomain.Evidence;
//創建新的輔程序域
this.domainJob = AppDomain.CreateDomain("Mag.Web.MainSrv.Jobs",adevidence,setup);
//輔程序域,dll都加載在這,更新頻繁,這是一定要設置的。
this.domainJob.SetShadowCopyFiles();
加載dll
{
string [] str = config.Split(',');
string strDllFilePath = string.Format("{0}{1}.dll",AppDomain.CurrentDomain.BaseDirectory,str[1]);
string strClassName = str[0];
if(!System.IO.File.Exists(strDllFilePath))
{
//throw new Exception("指定的文件不存在");
Mag.Windows.Interface.Log.AddErr("buildWorker","指定的文件不存在" + strDllFilePath);
return null;
}
Mag.Windows.Interface.IDo iDo=null;
try
{
//使用當前程序域加載
// System.Runtime.Remoting.ObjectHandle objHandle = Activator.CreateComInstanceFrom(strDllFilePath,strClassName);
// object objBuild = objHandle.Unwrap();//建立對像
System.Runtime.Remoting.ObjectHandle objHandle = pJobDomain.CreateInstanceFrom(strDllFilePath,strClassName);
object objBuild = objHandle.Unwrap();
//會引起找到不dll或依賴的項的錯誤。
// object objBuild = pJobDomain.CreateInstanceAndUnwrap(strDllFilePath,strClassName);
//會首先使用緩存中的dll
// System.Reflection.Assembly asm = pJobDomain.Load(str[1]);
// object objBuild = asm.CreateInstance(str[0]);
if(objBuild==null)
Mag.Windows.Interface.Log.AddErr("buildWorker","創建對象失敗");
else
iDo = (Mag.Windows.Interface.IDo)objBuild;
}
catch(Exception ee)
{
// throw ee;
Mag.Windows.Interface.Log.AddErr("buildWorker",ee);
}
return iDo;
}