在dotnet中如何使用資源

來源:互聯網
上載者:User
如何使用資源檔

--------------------------------------------------------------------------------

摘要
.NET 中有一套非常完善的地方化系統被定義在 System.Resources 名字空間中。不過大多數人都被 MissingManifestResourceException 這個錯誤困惑著。本文就是要讓大家瞭解什麼是資源檔,它有什麼用處以及如何正確的調用從而避免一些"奇怪"的錯誤,包括 MissingManifestResourceException 這個常見錯誤。

--------------------------------------------------------------------------------

目錄
本文來源以及最終目的
什麼是資源檔
資源檔類型
調用資源檔的幾種方法
如何準確的定義資源檔的邏輯位置
推薦工具
總結
參考資訊
關於作者

--------------------------------------------------------------------------------

本文來源以及最終目的
最近作者在新聞群組中看到許多有關資源檔的問題,而大多數人都有 MissingManifestResourceException 這個非常時髦的錯誤。所以作者考慮了一下,決定不想再讓更多的人把時間都浪費在這個問題上了。這就是這篇文章的誕生原因。而最終目的除了讓這個問題在新聞群組上消失之外還要讓大家在 10 分鐘內徹底掌握資源的調用,從而成為真正的資源高手!:)

--------------------------------------------------------------------------------

什麼是資源檔
在 .NET 中準備 World-Ready 程式時需要三步,Globalization,Localizability 和 Localization。在這第三步的 Localization 中就是使用資源檔最常見的地方。(本文不討論 World-Ready 程式,或許以後在另一篇文章中)因為程式的邏輯介面需要與資源介面隔離,而資源介面就是我們所說的資源檔。顧名思義,一個資源檔中當然全是資源,不過,什麼是資源?這裡所謂的資源就是程式中可利用的資料,譬如:字串、圖片和任何位元據,包括任何類型的檔案。注意一個資源檔可以有多種語言版本,舉例,一個 Strings.resources 檔案可以有英語版、簡體中文版、繁體中文版等。 ResourceManager 可以自動根據檔案名稱來確認調用哪個版本。不同的版本只要在檔案名稱中添入地區語言就可以了。比如,我們的 Strings.resources 是預設版,英語版的可以是 Strings.en-US.resources(美國英文),簡體中文的可以是 Strings.zh-CHS.resources(簡體中文),而繁體中文的就可以是 Strings.zh-CHT.resources(繁體中文)。所謂的預設版就是當找不到適當的資源版本時用的資源,一般都是英文。預設檔案應當被嵌入到主 Assembly 中,這樣就不會發生找不到資源的錯誤。在 VS.NET 中將一個檔案的屬性設為 Embedded Resource 可以使資源被嵌入到主 Assembly 中。

--------------------------------------------------------------------------------

資源檔類型
System.Resources 名字空間支援三種資源檔:
.txt 檔案,只能有字串資源。因為不能被嵌入到 Assembly 中,所以很容易暴露,被客戶修改。最大缺點是僅支援字串資源,所以不推薦使用。
.resx 檔案,由 XML 組成,可以加入任何資源,包括二進位。同樣不能被嵌入到 Assembly 中。在 System.Resources 名字空間中有專用讀寫的類。VS.NET 建立這種檔案然後將其轉成 .resources 檔案並根據設定將其嵌入到 Assembly 中。
.resources 檔案,PE 格式,可以加入任何資源。唯一可以被嵌入到 Assembly 的檔案,在 System.Resources 名字空間中有專用讀寫的類。

--------------------------------------------------------------------------------

調用資源檔的幾種方法
ResourceManager 可以根據不同的 UICulture 設定返回不同的本地資源(這與 World-Ready 程式有關,在此不討論),我們只需知道調用資源用到它就可以了。接下來讓我們看看如何調用每一種:
.txt 檔案:
不可以直接調用,得先將其轉換成 .resources 檔案才能使用。(關於如何轉換請看"推薦工具")
.resx 檔案:
可以用 ResXResourceReader 來做讀取,但是這種方法不直觀,不推薦直接調用 .resx 檔案。正確的方法是將其轉換成 .resources 檔案,然後用 ResourceManager 作讀取工作。注意如果是在 VS.NET 中添加的 .resx 檔案,那麼它們自動被設為 Embedded Resource,轉成 .resources 檔案後被嵌入到 Assembly 中。
.resources 檔案:
分成兩種情況:
被嵌入或編譯成 Satellite Assembly:
用 ResourceManager 的各種 constructor 來獲得在 Assembly 中的資源。
單獨檔案,沒被編譯或嵌入到 Assembly 中:
可以用 ResourceManager.CreateFileBasedResourceManager 來獲得資源集(ResourceSet),就是所有的資源。
特殊情況:
還有一種特殊情況,那就是當你直接嵌入一資源時,也就是說,不通過一個資源檔而直接將一資源嵌入到 Assembly 中。這可以在 VS.NET 中通過設定一檔案的 Build 屬性為 Embedded Resource 實現。在這種情況下 ResourceManager 就沒有用了,因為它只能擷取 .resources 資源檔(在或不在 Assembly 中)。那麼如何調用這類的資源呢?不難,我們需要利用一些 Reflection 中的特徵。別怕,不是讓你再學 Reflection,其實我們只要瞭解一些 System.Reflection.Assembly 這個類中的一些函數就可以了。有三個相關函數,不過我們只需要 Assembly.GetManifestResourceStream 這個函數。這個函數將一嵌入到 Assembly 中的資源以 stream 的方式返回,而我們可以將這個 stream 轉成在 .NET 中可用的對象。比如,如果嵌入資源是一圖片,那麼我們可以利用 New Bitmap(Stream) 這個 Bitmap 的 constructor 獲得這個圖片資源的 Bitmap 對象。
註:在這裡僅介紹怎樣獲得不同的資源的方法,關於怎樣用各個類與函數請參看有關文檔。

--------------------------------------------------------------------------------

如何準確的定義資源檔的邏輯位置
我想這是許多人最關注的一段了!在這裡作者將解說如何正確的填寫 ResouceManager(String, Assembly) 這個 constructor,還有如何正確的填寫 Assembly.GetManifestResourceStream(String),因為它們兩個的原理是相同的。看過了上面的描述,到了這裡就簡單多了。這裡主要討論的是怎麼填寫那個 String。這個 String 就是資源的完整名,一個完整名由它的名字空間和檔案名稱前部分(BaseName)組成。例如,如果預設名字空間(root namespace)是 DefaultNamespace,資源檔的名字是 Strings.en-US.resources,那麼它的完整名就是 DefaultNamespace.Strings。這個很簡單,不過怎樣確定名字空間呢?這就有些奇怪了,因為 C# 的編譯器與 VB.NET 的編譯器有些不同。作者在這裡分別給出兩個編譯器怎樣給嵌入資源自動添加命名空間:
C#
它自動添加 default namespace(與 root namespace 相同),但也添加子檔案夾的名字。例如,在 Subfolder 子檔案夾下放的資源檔 Strings.en-US.resources,它的完整名是 default namespace + subfolder + base name = DefaultNamespace.Subfolder.Strings
VB.NET
在 VB.NET 中就很簡單了,它自動給嵌入資源添加 root namespace。不管你在哪個子檔案夾中放置資源檔,資源檔的完整名永遠是 root namespace + base name。
根據上面的描述,如果我們使用 C#,用 VS.NET 在 NewFolder 這個子檔案夾中添加了一個叫 Images.resources 的資源檔,那麼我們應該用以下代碼擷取這些資源,假設 default namespace 是 MyDefault:
ResourceManager res = new ResourceManager("MyDefault.NewFolder.Images", this.GetType().Assembly);
但如果我們用 VB.NET 的話,就應該這樣:
Dim res As New ResourceManager("MyDefault.Images", Me.GetType().Assembly)

--------------------------------------------------------------------------------

推薦工具
resgen.exe:SDK 中的工具,專門用來做資源檔類型之間的轉換。支援 .txt <-> .resx <-> .resources 之間的轉換。
Resourcer:專門用來建立資源檔,簡單易用,支援 .resx 與 .resources 檔案格式。(http://www.aisto.com/roeder/dotnet)
.NET Reflector:用來瀏覽 Assembly。如果你不確定一個資源檔的完整名時可以用這個工具在 Assembly 中查看。(http://www.aisto.com/roeder/dotnet)

--------------------------------------------------------------------------------

總結
本文中談及了以下內容:
什麼是資源
什麼是資源檔
.NET 中有哪幾類資源檔
如何定義資源檔的邏輯位置
調用資源檔的幾種方法
本文通過正確定位資源檔而解決了那個非常時髦的 MissingManifestResourceException。本文給了您一個很豐富資源調用經驗。想讓您完全瞭解有關資源檔的任何可能問題,當然也會有漏洞。如果有的話希望大家諒解!

--------------------------------------------------------------------------------

參考資訊
以下是一些文檔的連結,如果您的協助是中文的話請在 MSDNVS 後添加".2052":
Resource File Generator (Resgen.exe)
ms-help://MS.VSCC/MS.MSDNVS/cptools/html/cpgrfresourcefilegeneratorutilityresgenexe.htm
Resources in Applications
ms-help://MS.VSCC/MS.MSDNVS/cpguide/html/cpconcreatingusingresources.htm
Resource Fallback Process
ms-help://MS.VSCC/MS.MSDNVS/cpguide/html/cpconpackagingdeployingresources.htm #cpconpackagingdeployingresourcesanchor1

--------------------------------------------------------------------------------

關於作者
作者:袁偉(Kefroth)


相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。