在VS中引用類庫時有多種方法,其中用的最多的就是在引用時選擇項目選項卡引用本解決方案下的類庫項目和選擇瀏覽選項卡直接引用類庫DLL檔案,實際上這兩種引用方式略有不同,今天就為大家總結下。
C#本地項目(控制台,winform)
- 引用類庫項目,這時對引用DLL類庫做出任何修改會立刻生效,不用儲存和產生類庫。如果刪除類庫項目,則本項目中引用的DLL也被刪除。
- 引用類庫DLL,這時對類庫的修改,需要先產生類庫項目,再產生本項目才會生效。 如果刪除或改變類庫DLL的目錄,則本項目中的引用會指向本項目bin\debug目錄下產生的DLL(但是前提是在刪除或改變類庫DLL的目錄後,不要立即重建本解決方案,因為重建解決方案和產生解決方案的原理不一樣,重建解決方案時VS會先清空本項目bin\debug目錄下原先產生的DLL類庫檔案也就是先清空解決方案,再產生本解決方案,而這時本項目bin\debug目錄中已經沒有原先產生的DLL類庫檔案了,產生解決方案時當然會報錯,你必須先產生解決方案或運行本項目,這時本項目中的引用才會指向本項目bin\debug目錄下原先產生的DLL類庫檔案,並將這個新的引用資訊儲存到專案檔,這時你再重建解決方案VS就不會去刪除bin\debug目錄下原先產生的DLL類庫檔案了,但是如果該DLL類庫又引用了其它類庫項目(即本項目和這些其它的類庫項目之間是間接參考關聯性,關於間接引用詳情請見後面的附加內容),那麼這時對本項目重建解決方案,VS還是會去將bin\debug目錄下該DLL類庫檔案引用的其它類庫項目的DLL檔案給刪除掉,所以這時如果本項目引用的DLL類庫調用了這些其它類庫項目中的代碼可能會報錯,所以請不要輕易去刪除或改變項目中所引用DLL類庫檔案的目錄)。但是如果還原該類庫DLL到原目錄,則本項目中的引用又會指向該類庫DLL。
- 以上無論哪種方式都要將引用的DLL檔案的屬性設定為複製到本地,否則運行本項目時會報錯。
ASP.NET Web應用程式
- 引用類庫項目,這時對引用DLL類庫做出任何修改會立刻生效,不用儲存和產生類庫。如果刪除類庫項目,則本項目中引用的DLL也被刪除。
- 引用類庫DLL,這時對類庫的修改,需要先產生類庫項目,再產生本項目才會生效。 如果刪除或改變類庫DLL的目錄,則本項目中的引用會指向本項目bin目錄下產生的DLL(但是前提是在刪除或改變類庫DLL的目錄後,不要立即重建本解決方案,因為重建解決方案和產生解決方案的原理不一樣,重建解決方案時VS會先清空本項目bin目錄下原先產生的DLL類庫檔案也就是先清空解決方案,再產生本解決方案,而這時本項目bin目錄中已經沒有原先產生的DLL類庫檔案了,產生解決方案時當然會報錯,你必須先產生解決方案或運行本項目,這時本項目中的引用才會指向本項目bin目錄下原先產生的DLL類庫檔案,並將這個新的引用資訊儲存到專案檔,這時你再重建解決方案VS就不會去刪除bin目錄下原先產生的DLL類庫檔案了,但是如果該DLL類庫又引用了其它類庫項目(即本項目和這些其它的類庫項目之間是間接參考關聯性,關於間接引用詳情請見後面的附加內容),那麼這時對本項目重建解決方案,VS還是會去將bin\debug目錄下該DLL類庫檔案引用的其它類庫項目的DLL檔案給刪除掉,所以這時如果本項目引用的DLL類庫調用了這些其它類庫項目中的代碼可能會報錯,所以請不要輕易去刪除或改變項目中所引用DLL類庫檔案的目錄)。但是如果還原該類庫DLL到原目錄,則本項目中的引用又會指向該類庫DLL。
- 以上無論哪種方式都要將引用的DLL檔案的屬性設定為複製到本地,否則運行本項目時會報錯。
ASP.NET 網站
- 引用類庫項目,這時對引用DLL類庫做出任何修改會立刻生效,不用儲存和產生類庫。如果刪除類庫項目,則本項目中引用的DLL也被刪除。
- 引用類庫DLL,這時對類庫的修改,需要先產生類庫項目,再產生本網站項目才會生效。 如果刪除或改變類庫DLL的目錄,本項目中的引用還是會指向原先DLL類庫檔案的目錄(不過ASP.NET網站是通過refresh檔案指向該DLL檔案的地址),不會指向本項目Bin目錄下產生的DLL,但是在對本項目產生解決方案時,會產生一個警告指示找不到所引用DLL類庫項目的原始檔案,如果還原該DLL類庫到原目錄,警告就會消失。此外對ASP.NET網站項目重建解決方案時,VS不會去刪除本項目Bin目錄下的任何檔案,所以即便是刪除或改變本項目所引用DLL類庫檔案的目錄,由於本項目的Bin目錄下的所有DLL檔案都還在,因此本項目的所有代碼還是可以正確運行。
- ASP.NET 網站引用的DLL檔案都會複製到本網站的Bin目錄。
附加內容:這裡順便談談類庫引用鏈中的直接引用和間接引用的一個小問題
首先來談談什麼叫引用鏈,大家知道C#項目中的類庫還可以引用其它的類庫,那麼假如現在有3個類庫:LibA、LibB、LibC,這三個類庫存在參考關聯性:LibA<-LibB<-LibC(其中A<-B表示類庫B引用類庫A產生的DLL檔案),那麼我們就說這三個類庫LibA<-LibB<-LibC是一條引用鏈(LibA是引用鏈的頭,LibC是引用鏈的末尾)。
- 直接引用:直接參考資料表示兩個類庫在引用鏈中的位置是相鄰的,比如上面的LibA和LibB以及LibB和LibC。
- 間接引用:間接參考資料表示兩個類庫在引用鏈中的位置是不相鄰的,比如上面的LibA和LibC。
在引用鏈的直接參考關聯性中,比如LibA<-LibB,我們都知道,類庫項目LibB在產生後會將類庫項目LibA產生的DLL檔案,複製到LibB項目自己的bin/Debug目錄下,這沒有什麼問題。在引用鏈的間接引用中,比如LibA<-LibB<-LibC中,我們知道產生該引用鏈中的三個類庫項目後,LibC的bin/Debug目錄下肯定有LibB.DLL,因為LibC和LibB是直接參考關聯性,LibB的bin/Debug目錄下肯定有LibA.DLL,因為LibB和LibA是直接參考關聯性。但是問題是LibC的bin/Debug目錄下是否也有和其存在間接參考關聯性的類庫項目LibA的DLL檔案LibA.DLL?
經過多次實驗,我發現如果類庫項目LibB中使用了類庫項目LibA中的成員時(即LibB不僅引用了LibA的DLL檔案,還使用了LibA的DLL檔案,比如調用了LibA的方法,聲明了LibA中類的對象等,但切記只用using匯入LibA中的命名空間不叫使用),那麼在引用鏈LibA<-LibB<-LibC產生後,類庫項目LibC的bin/Debug目錄下會同時產生LibA.DLL和LibB.DLL。但是如果類庫項目LibB中沒有使用類庫項目LibA中的成員時(即LibB只引用了LibA,但是LibB中完全沒有使用LibA),類庫項目LibC的bin/Debug目錄下就只有LibB.DLL。
所以你會發現其實VS在產生引用鏈時很聰明,因為在產生LibA<-LibB<-LibC中的LibC時,VS會去查看與LibC存在直接參考關聯性的類庫項目LibB的組建目錄bin/Debug下有幾個DLL檔案,那麼在本例中由於LibA和LibB是直接參考關聯性,那麼LibB的bin/Debug下肯定有兩個DLL檔案LibA.DLL和LibB.DLL。那麼這時VS就會去探查LibB.DLL中是否使用了LibA.DLL。如果使用了VS就會把LibA.DLL、LibB.DLL同時Copy到LibC的bin/Debug目錄下。如果沒有使用LibA.DLL,那麼VS會認為LibA.DLL是多餘的,只會把LibB.DLL Copy到LibC的bin/Debug目錄下。
但是上面這段話不是絕對的,因為我發現如果將引用鏈末端的類庫項目LibC換成Asp.net網站或Asp.net應用程式,其產生DLL檔案的原理是不一樣的,說明.net的每種項目引用DLL檔案時都有自己的一套建置規則,上面只討論了類庫項目的建置規則。