程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> Effective C#第4章:創建基於二進制的組件

Effective C#第4章:創建基於二進制的組件

編輯:關於C#

隨著類的數量增加,創建二進制的組件就變得很平常了:你想分離部分功能 。所有不同的是,二進制組件可以讓你獨立的保存這些離散的功能。創建的組件 程序集可以方便的共享邏輯,方便交叉語言 編程,以及方便布置。

在.Net程序就是組件包,每一個程序什麼樣可以隨時更新和發布。你應該已經知 道,基於程序集之間的應用程序是多麼容易更新呀,程序集之間的偶合是多麼好 呀! 最小偶合就是說更多的是減少了程序集之間復雜的依懶關系。同時也意味著 你可以簡單的更新小塊新 的程序集。這一章就是關於創建簡單易用,容易布置 ,以及容易更新的程序集。

.Net環境中的應用程序可以由多樣的二進制 組件組成。隨後,你可以獨立的更新這些組件,也就是可以在一個多程序集應用 程序中安裝與更新一個程序集。但你必須明白一件事,那就是CLR是如何發現和 載入這些程序集的。在你創建這些二進制組件時,你也就必須創建符合這些明確 期望的組件。接下來就介紹這一概念。

CLR並不會在程序啟動時加載全部 的引用程序集。更合適的作法是當運行時須要程序的成員時,加載器才解決程序 集的引用問題。這可能是調用一個方法或者訪問數據,加載器先查找引用的程序 集,然後加載它,然後JIT編譯須要的IL。

當CLR須要加載一個程序集時 ,先是斷定那個文件要加載。程序集的元數據包含了對所有其它程序集的引用記 錄,這個記錄有強名稱和弱名稱之分。一個強名稱(程序集)由四部分組成:程序 名,版本號,語言屬性(譯注:這裡的語言范指區域性特定的信息,如關聯的語 言、子語言、國家/地區、日歷和區域性約定),以及公開密鑰。如果程序集不是 一個強名稱程序,那麼就只記錄了程序集名。如果你的程序是一個強名稱程序集 ,那麼你的程序集就不太可能被一些惡意的組件(程序集)所取代。強程序集還可 以讓你用配置文件對組件的版本進行配置,是新的,還是先前的。

確定 正確的程序集以後,CLR接來就斷定這個程序集是否已經在當前的應用程序中加 載。如果是,就用原來的。如果不是,CLR就繼承查找程序集。如果程序是強名 稱的,CLR就先在全局程序緩存(GAC)中查找,如果不在GAC中,加載器就檢測代 碼目錄(codebase directory,譯注,這裡只是譯為代碼目錄,其實並不是源代 碼所在的目錄)中的配置文件,如果當前代碼目錄存在,那就是唯一被搜索程的 目錄了。如果在代碼目錄中沒有找到所要的程序集,那麼加載就失敗。

如果沒有直接的代碼目錄,加載器會搜索預先設定的目錄集:

* 應用程 序目錄。也就是與主應用程序集同在的位置。

* 語言目錄。這是一個在 應用程序目錄下的子目錄,這個目錄與當前語言名匹配。

* 程序集子目 錄。這是一個與程序集同名的子目錄,這兩個可以組合成這樣: [語言]/[程序 集名]

* 私有的運行目錄(binPath)。這是一個在應用程序配置文件中定 義的私有目錄。它同樣可以和語言和程序集名組合: [bin目錄]/[程序集名], 或者[bin目錄]/[語言], 還可以是:[bin目錄]/[語言]/[程序集名]。

從 這個討論中你應該明白三個內容:第一,只有強名稱程序集才能放到GAC中。其 次,你可以通過配置文件來修改默認的行為,從而升級程序中個別的強名稱程序 集。第三,強名稱程序集可以阻止對程序集的惡意篡改,從而提供更安全的應用 程序。

了解CLR是如何加載程序集的,有利於在實際操作中考慮如何創建 和更新組件。首先,你應該使用強名稱程序集,把所有的元數據信息都記錄下來 。當你在VS.net中創建一個項目時,你應該把assemblyInfo.cs文件中的所有屬 性都填滿,包括完整的版本號。這會讓你在後面的升級中更簡單的。VS.net在 assemblyInfo.cs中創建三個不同的部份,首先就是信息報告:

[assembly: AssemblyTitle("My Assembly")]
[assembly: AssemblyDescription
 ("This is the sample assembly")]
#if DEBUG
[assembly: AssemblyConfiguration ("Debug")]
#else
[assembly: AssemblyConfiguration ("Release")]
#endif
[assembly: AssemblyCompany ("My company")]
[assembly: AssemblyProduct("It is part of a product")]
[assembly: AssemblyCopyright ("Insert legal text here.")]
[assembly: AssemblyTrademark("More legal text")]
[assembly: AssemblyCulture("en-US")]

最後一條, AssemblyCulture 只針對本地化程序集。如果你的程序不包含任何的本地化資源 ,就空著。否則就應該遵從RFC1766標准填寫語言描述信息。

接下來的部 份就是版本號,VS.net是這樣記錄的:

[assembly: AssemblyVersion("1.0.*")]

AssemblyVersion包含4 個部份:主版本號.副版本號.編譯號.修訂號,星號就是告訴編譯器用當前時間 來填寫編譯號和修訂號。編譯號就是從2000年1月1號起的天數,而修訂號則是從 當天凌晨起的秒數除以2。這樣的算法可以確保修訂號是不斷遞增的:每次編譯 後的號碼都會比前一次高。(譯注:我有一點不明白的,就是如果我把本機時間 修改了呢?或者兩台機器上的時間不一致,會有什麼問題呢?當然,這並不會有 什麼太大的問題。)

對於這一版本號的算法,好消息是兩個編譯的版本不 會有完全相同的版本號。壞消息就是在你編譯並發布後,要記住這個版本號。我 個人比較喜歡讓編譯器給我生成編譯和修訂號。通過記錄發布時的編譯號,我就 知道最後的版本號了。我從來不會忘記在我發布一個新程序集時修要改它的版本 號。但也有例外,COM組件是在你每次編譯後自動注冊的。如果還讓編譯器自己 生成編譯號後然後注冊它,那麼很快就讓注冊表裡填滿了無用的信息。

最後一部份就是強名稱信息:

[assembly: AssemblyDelaySign (false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

應該考慮為所有 的程序集都創建強名稱,強名稱程序集可以防止別人的篡改,而且可以為單個應 用程序獨立更新個別程序集。然而,你應該在ASP.net應用程序中避免使用強程 序集;局部安裝的強名稱程序集不會正確的加載。同樣,強名稱程序集必須用 AllowPartiallyTrustedCallers特性進行修飾,否則它們不能被非強名稱程序集 訪問(參見原則47)。

實際在更新一個組件時,公共的和受保護的接口部 份必須在IL語言層上是兼容的。也就是說不能刪除方法,不能修改參數,不能修 改返回值。簡單的說,沒有一個組件願意在引用你的組件後要重新編譯。

你可以添加配置信息來修改引用的程序集。配置信息可以存儲在不同的 位置,這取決於你想如何更新組件。如果是一個簡單的應用程序,你可以創建一 個應用程序配置文件,然後把它存放在應用程序目錄就行了。如果是配置所以使 用同一個組件的應用程序,你可以在GAC中創建一個發布策略文件。最後,如果 是全局的修改,你可以修改machine.config文件,這個文件在.Net進行時的配置 目錄裡(參見原則37)。

實際操作中,你可能從來不用修改 machine.config文件來更新你的程序集。這個文件包含了基於整台機器的信息。 你可以通過應用程序配置文件來更新單個應用程序配置,或者使用一個發布策略 來更新多個程序公用的組件。

這是一個XML配置文件,它描述了存在的版 本信息和升級後的信息:

<dependentAssembly>
  <assemblyIdentity name="MyAssembly"
   publicKeyToken="a0231341ddcfe32b" culture="neutral" />
 <bindingRedirect oldVersion="1.0.1444.20531"
   newVersion="1.1.1455.20221" />
</dependentAssembly>

你可以通過這個配置文件來標識 程序集,舊版本,以及升級後的版本。當你安裝和更新了程序集後,你就要更新 或者創建一個恰當的配置文件,然後程序程序就可以使用新的版本了。

如果你的軟件是一個程序集的集合:你希望個別的更新它們。通過一次更新一個 程序集,你須要做一些預先的工作,那就是第一次安裝時應該包含一些必要的支 持升級的信息。

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved