標籤:style blog http color strong 檔案
先來看一段程式:
<pre name="code" class="vb">Imports System.Configuration '設定檔命名空間Imports System.Reflection '反射命名空間Imports IDAL '引用介面層Public Class DataAccess '程式集名稱(同時代表命名空間名稱):DAL Private Shared ReadOnly AssemblyName As String = System.Configuration.ConfigurationManager.AppSettings("assname") '資料庫類型:Sql Private Shared ReadOnly db As String = System.Configuration.ConfigurationManager.AppSettings("DB") '建立D層類SqlUserInfoDAL的執行個體 Public Shared Function CreateUserInfo() As IDAL.IUserInfo Dim dalUserInfoName As String = AssemblyName & "." & db & "UserInfoDAL" '要執行個體化的D層類的名稱 Return CType(Assembly.Load(AssemblyName).CreateInstance(dalUserInfoName), IUserInfo) End Function
對於學過反射+設定檔+抽象工廠實現資料訪問的人來說,這小段程式還是很容易理解的。我將這段程式用在了機房收費系統個人重構版中。:
但是在運行過程中卻報了錯:
未能負載檔案或程式集“DAL”或它的某一個依賴項。系統找不到指定檔案。
通過查資料,知道了一種解決方案:將DAL層的DAL.dll檔案複製到UI層相應的目錄下,。
之後,程式正常運行,並通過CreateUserInfo()建立出了SqlUserInfoDAL的執行個體。
有了成功的經驗,我便做了如下操作:
- 在DAL層,添加了一個新的類:SqlWorkLogDAL
- 在DataAccess中,添加了一個新的方法:CreateWorkLog()
如下所示:
'建立D層類SqlWorkLogDAL的執行個體 Public Shared Function CreateWorkLog() As IDAL.IWorkLog Dim dalWorkLogName As String = AssemblyName & "." & db & "WorkLogDAL" '要執行個體化的D層類的名稱 Return CType(Assembly.Load(AssemblyName).CreateInstance(dalWorkLogName), IWorkLog) End Function
但是運行後,還是報了錯,不過這次錯誤不一樣:
未將對象引用設定到對象的執行個體。
通過查資料,也找到了答案:修改DAL層--屬性--編譯--產生輸出路徑,將產生輸出路徑改到UI層\bin\Debug檔案夾下。
雖然兩種解決方案不一樣,但是本質都是把DAL層的DAL.dll檔案放到UI層。
那麼,為什麼第一種解決方案只有“短暫療效”,而第二種方法可以“根治”呢?
這時,我做了個嘗試,我不去修改路徑,而是再次把DAL層中的DAL.dll檔案複製並替換我剛才複製到UI層的檔案。
結果成功了。
這就說明了:兩次複製的檔案並非同一個檔案,雖然它們都叫DAL.dll,但是在檔案內部,它們一定發生了變化。
這裡我們就要說說,dll檔案是怎麼產生的了。
每個程式集下面都有兩個檔案夾bin和obj,
bin目錄用來儲存項目產生後程式集,obj目錄用來儲存編譯結果。編譯是分模組進行的,編譯整個完成後會合并為一個.dll或.exe檔案儲存到bin目錄下。而且採用增量編譯的方式。
所以,當我添加了一個新的類SqlWorkLogDAl後,產生的DAL.dll已經不是原來的DAL.dll了。
複製的方式的缺陷在於:只要DAL層發生變化,就得通過手動複製來更新U層的DAL.dll檔案。但是修改路徑,就不用我們管了,它會自動將最新的DAL.dll檔案產生到UI層。
那麼為什麼要把D層的.dll檔案在U層產生呢?
這就要知道Assembly.Load()是怎麼定位程式集了?
當你只給定程式集名稱時,如“DAL”,那麼CLR只會在應用程式的目錄下尋找,而咱們的應用程式在UI層,所以要在U層有DAL.dll。
問題又來了:
在U層,有Entity.dll,有BLL.dll,有DataAccess.dll……為什麼就是沒有DAL.dll,為什麼只有它需要修改產生路徑?
這裡就要看看程式的包圖了:
---->代表依賴,也表示引用,那麼從UI層看,UI層可以直接或間接地引用Facade層,BLL層,DataAccess層,IDAL層,但是沒有引用DAL層,所以別的層的.dll檔案會出現在U層,而DAL層的.dll檔案沒有出現在U層。
文章中,如果有理解得不對的地方,還請大家批評指正。