1. 程式人生 > >解讀經典-《C#高階程式設計》第七版-Chapter1-.Net體系結構-Page13-20

解讀經典-《C#高階程式設計》第七版-Chapter1-.Net體系結構-Page13-20

01

程式集

 

程式集是包含編譯好的、基於.Net Framework的程式碼邏輯單元。一般來說,在Visual Studio中的一個專案即一個程式集,而一個專案中包含多種不同的程式碼檔案。程式集分為可執行程式集和庫程式集,比如一個Winform專案就編譯為可執行程式集,而Winform專案所包含的其他庫專案則編譯為庫程式集。可執行程式集包含主程式入口點,而庫程式集不包含。

 

程式集的特點是,它是完全自描述的,這和傳統的COM元件非常不同,而自描述的程式集正是要解決傳統COM元件的資訊分離問題。一個COM元件,往往包含了庫檔案(dll、ocx等檔案),同時COM需要註冊到登錄檔生成GUID以供呼叫,這便對作業系統有了強依賴,有些情況下還需要讀取型別庫(lib檔案),這樣一來一個COM元件被分離成三部分,一致性就存在很大的問題。而程式集自描述的“元資料”儲存了程式集本身以及程式集所依賴的庫檔案的資訊,從而能夠對一致性進行檢查而避免了因為運行了不一致的程式集而導致執行中發生錯誤。對於程式集的一個應用案例就是,我之前用其他更古老的語言開發時,要做自動升級功能時,只能簡單的以檔案修改日期的新舊來判斷是否應該更新,而類庫之間相互依賴關係,那根本就無法知道了,除非釋出應用自帶一個獨立的配置檔案來描述這些關係。而對於.Net來說,有了程式集,配置是自帶在程式碼裡的,就可以做到非常精細化的升級控制,從而保證程式的正確和安全的更新。

 

程式集分為私有程式集和共享程式集。

  1. 私有程式集可以理解為“拷貝即可執行的綠色程式包”,它不依賴於登錄檔,程式集只要位於主執行程式的所在目錄或子目錄下,即可正確執行。
  2. 共享程式集當然是為了“共享”。比如一個公司釋出了多個產品,它們依賴於相同的底層類庫,公司釋出它的產品時,不想每個產品都發布一份底層類庫的拷貝,那可能導致不同拷貝間的不一致以及安裝包比較龐大,此時就適合使用共享程式集。當然為了實現共享,程式集就需要放在作業系統的公共空間中(全域性程式集快取GAC),這就可能導致不同公司程式集的名稱衝突,因此.Net提供了私鑰加密法為共享程式集生成一個能保證唯一性的名稱(強名strong name)。

 

因為程式集中包含了描述自身的元資料,所以可以程式設計訪問這些元資料,這個技術稱為“反射”。使用反射可實現業務邏輯的“解耦”,是個比較常用的程式碼優化手段。但反射也不應該過度使用,我的系統裡很少反射,因為必須用反射的地方其實很少。我的程式設計觀念是:業務邏輯應該首選使用“程式碼”來描述,而不是配置檔案,這樣形成的程式碼,是非常清晰容易閱讀、理解和維護的。我非常討厭Java界的那種想用配置描述一切的思路。

 

02

.Net Framework類

.Net的強大功能,給程式設計師帶來的最大的感受可能是來自於.Net Framework類庫。.Net類庫非常全面,其實學習.Net,很大的部分就是學習.Net類庫。

 

這裡補充下我對.Net類庫的使用感受。按照我自己的使用習慣,我自己為專案建立的自有類庫非常“瘦”,即非常簡單。而我非常不讚賞的是,看到很多初學者,也包括一些.Net高手,都喜歡在.Net類庫之上再搞一層自己的“類庫”,翻開其程式碼看看,大部分是將.Net類庫的一部分抽取出來,簡單封裝一下自己用,這個封裝可能就是一個兩三行程式碼的方法,就這樣封裝出大量的類庫和方法。其目的很明顯:我覺得這個是常用的功能,所以封裝一下,以後用它就比較方便。這在Java,C#之前的程式設計時代,可能是正確的,因為那時候沒有這麼全面而強大的類庫,但對於.Net的使用,我是拒絕這麼做的,理由如下:

1)版本的閹割:.Net類庫非常廣泛,而封裝自己的類庫是個閹割版本,功能大大弱化。

2)思想的禁錮:有人說,我可以在合適的場景使用我的類庫,當我的類庫實現不了時,就去找.Net類庫的方法。但我可以明確的說,實際操作中這很難做到,原因就是:人的路徑依賴。當你長年累月的使用自己的類庫後,你必然大概率會忘記.Net類庫還有更好的實現方法,而傾向於自己去封裝新的方法。這就把自己禁錮在自己的一畝三分地裡,8年10年後,你大概率對.Net類庫還是不生疏的,只是掌握了一些簡單的功能。

而就算你真的每次都記得去.Net類庫找方法,長期下來很多場景被應用後,當你自己的類庫已經封裝了.Net類庫10個方法中的9個,那你這樣的“二傳手”封裝並沒有起到簡化開發的作用,意義又在哪裡?

3)程式碼複雜化:在你的程式設計思想被禁錮後,程式碼複雜化隨之而來。.Net類庫有非常豐富的“過載”方法,即一個物件的方法,針對不同的應用場景會有多達十幾種封裝方法,在不同的應用場景使用合適的方法,可以寫出非常簡潔優美的程式碼。而自己封裝的類庫,往往只能封裝其中的一兩種過載方法,結果是,在一種場景中寫程式碼是方便了,而在所有其他場景中寫程式碼又必須自己寫補充程式碼來達到和.Net過載方法同樣的功能,程式碼反而變得臃腫。

 

所以,我的方法是,在問題的源頭上,就避免思想被禁錮的可能,即原則上不封裝自己的類庫,除非.Net類庫就是沒相關實現。抱著開放的態度,有問題隨時在.Net類庫中尋找方法。而我確實發現,即使當解決方案規模達到了近百專案,可能用到的自封裝類庫也不超過幾個封裝類以及其中的20個方法。

 

一個有趣的事實是,.Net類庫的大部分,都是使用C#編寫的。

 

03

名稱空間

名稱空間是避免.Net類名衝突的方式。名稱空間是可以巢狀的,比如System空間下包含子空間System.Array。

 

第一章講解完畢,下回我們開始講解第二章:核心C#。

 

曾經覺得元資料很玄乎,現在看看其實沒什麼,即基礎描述性資料,資料的資料。附篇2篇文章可瞭解一下元資料。

 

覺得文章有意義的話,請動動手指,分享給朋友一起來共同學習進步。

 

歡迎關注本人微信公眾號,更及時的關注最新文章(每週三篇原創文章,以及多篇專題文章):

附文:

李建忠:Metadata是.NET平臺的核心靈魂

C# 元資料描述

 

上一篇:解讀經典-《C#高階程式設計》第七版-Chapter1-.Net體系結構-Page6-13