如何让ASP.NET默认的资源编程方式支持非.ResX资源存储
之前寫了兩篇文章《.NET資源并不限于.ResX文件》(上篇、下篇),介紹了如何通過自定義ResourceManager的方式來擴展資源的存儲形式。在那篇文章中,我定義了三種基于獨立文件的ResourceManager(ResXResourceManager、BinaryResourceManager和XmlResoureManager)分別實現對.ResX,.Resource和.xml三種資源文件的訪問。在本篇文章中我們將實現自定義ResourceManager和ASP.NET之間的集成,讓ASP.NET現有的資源編程方式支持我們自定義的ResourceManager。
一、回顧一下之前創建的XmlResourceManager
二、創建自定義ResourceProvider
三、創建自定義ResourceProviderFactory
四、Global Resource編程
五、Local Resource編程
一、回顧一下之前創建的XmlResourceManager
本篇文章將會以我們之前創建的XmlResourceManager為例。通過自定義的XmlResourceManager,我們實現了將資源內容定義在了一個自定義結構的XML文件。該XML具有如下一個簡單的結構。
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <add name="Greeting4Chris" value="Merry Christmas!" /> 4: <add name="Greeting4NewYear" value="Happy Chinese New Year!" /> 5: </resources>和.ResX文件一樣,為了提供多多語言的支持,我們用帶有Culture Code后綴的文件名來區分資源文件所基于語言文化。如右圖所示,我在一個Web Application中,定義了兩套資源文件:Global Resource和Local Resource。兩種資源類型的概念,不用多說你也應該知道。前者是一個全局意義的資源文件,供所有Web頁共享;后者則是基于某個Web頁單獨使用的本地資源。
二、創建自定義ResourceProvider
要讓ASP.NET現有的資源編程方式將我們添加的XML作為資源存儲,必須了解ASP.NET內部采用的資源讀取機制。實際上,ASP.NET在后臺采用一個特殊的組件進行資源的讀取,這個組件就是ResourceProvider。我們只需要創建一個基于XmlResourceManager的自定義ResourceProvider,并將它注冊到ASP.NET中就可以了。
為此我創建了如下一個XmlResourceProvider,它實現了IResourceProvider。IResourceProvider具有一個GetObject方法和一個ResourceReader只讀屬性。前者實現了對指定鍵值的資源條目的讀取,后者則返回一個ResourceReader。在GetObject方法中,我們利用自定義的XmlResourceManager進行資源的獲取,而ResourceReader屬性的實現中,我們返回的我們之前創建的XmlResourceReader。
1: public class XmlResourceProvider:IResourceProvider 2: { 3: public XmlResourceManager ResourceManager { get; private set; } 4:? 5: public XmlResourceProvider(string directory, string baseName) 6: { 7: this.ResourceManager = new XmlResourceManager(directory, baseName); 8: } 9:? 10: public object GetObject(string resourceKey, CultureInfo culture) 11: { 12: return this.ResourceManager.GetObject(resourceKey, culture); 13: } 14:? 15: public IResourceReader ResourceReader 16: { 17: get 18: { 19: return new XmlResourceReader(Path.Combine(this.ResourceManager.Directory,this.ResourceManager.BaseName+".xml")); 20: } 21: }三、創建自定義ResourceProviderFactory
XmlResourceProvider創建完畢,但是它不能直接被注冊,我們需要創建一個對應的工廠類。為此,如下一個名稱為XmlResourceProviderFactory類被創建出來。
1: public class XmlResourceProviderFactory:ResourceProviderFactory 2: { 3: public override IResourceProvider CreateGlobalResourceProvider(string classKey) 4: { 5: string directory = HttpContext.Current.Server.MapPath("GlobalResources"); 6: return new XmlResourceProvider(directory, classKey); 7: } 8:? 9: public override IResourceProvider CreateLocalResourceProvider(string virtualPath) 10: { 11: string directory = HttpContext.Current.Server.MapPath(VirtualPathUtility.GetDirectory(virtualPath)); 12: string baseName = VirtualPathUtility.GetFileName(virtualPath); 13: return new XmlResourceProvider(directory, baseName); 14: } 15: }XmlResourceProviderFactory繼承自抽象類ResourceProviderFactory,并實現了兩個抽象方法CreateGlobalResourceProvider和CreateLocalResourceProvider。這兩個方法均返回一個ResourceProvider對象,它們分別用于基于Global Resource和Local Resource的讀取。在XmlResourceProviderFactory中,這兩個方法均返回一個XmlResourceProvider對象。所不同的是,CreateGlobalResourceProvider方法返回的XmlResourceProvider基于的資源文件是一個存儲在GlobalResources目錄下指定名稱(classKey)的XML文件,而CreateLocalResourceProvider返回的XmlResourceProvider基于的資源則是和當前訪問.aspx文件處于同級目錄下,并且名稱和.aspx文件同名的XML文件。
在web.config中,XmlResourceProviderFactory通過<system.web>/<globalization>配置節進行注冊,下面是相應的配置。
1: <?xml version="1.0"?> 2: <configuration> 3: <system.web> 4: <globalization uiCulture="zh-CN" resourceProviderFactoryType="Artech.ResourceAppBlock.XmlResourceProviderFactory, Artech.ResourceAppBlock.Lib"/> 5: <compilation debug="true"/></system.web> 6: </configuration>四、Global Resource編程
現在我們來驗證以下通過ASP.NET原生的資源編程模式是否能夠正常讀取我們指定的XML。我們先來演示Global Resource的讀取,為此我們創建了一個Web項目,并進行了如上的配置。如上面途中所示,我們在GlobalResources目錄下添加了3個XML文件,其中GreetingMessages.xml作為語言文化中性的資源文件,而GreetingMessages.en-US.xml和GreetingMessages.zh-CN.xml則基于美式英語和簡體中文。GreetingMessages.xml和GreetingMessages.en-US.xml具有相同的內容。
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <add name="Greeting4Chris" value="Merry Christmas!" /> 4: <add name="Greeting4NewYear" value="Happy Chinese New Year!" /> 5: </resources>而GreetingMessages.zh-CN.xml則為中文。
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <add name="Greeting4Chris" value="圣誕快樂!" /> 4: <add name="Greeting4NewYear" value="新年快樂!" /> 5: </resources> 現在我們創建一個文件名稱為Defualt.aspx的Web頁,并在其中放置兩個Label控件相應的HTML如下所示。 1: <body> 2: <form id="form1" runat="server"> 3: <div> 4: <asp:Label id="LabelGreeting4NewYear" runat="server" /> 5: <br/> 6: <asp:Label id="LabelGreeting4Chris" runat="server"/> 7: </div> 8: </form> 9: </body>在Page加載的時候,通過如下的代碼將兩個Label和相應的資源條目進行綁定。
1: protected void Page_Load(object sender, EventArgs e) 2: { 3: this.LabelGreeting4NewYear.Text = this.GetGlobalResourceObject("GreetingMessages", "Greeting4NewYear").ToString(); 4: this.LabelGreeting4Chris.Text = this.GetGlobalResourceObject("GreetingMessages", "Greeting4Chris").ToString(); 5: }在瀏覽器中訪問頁面,你會得到如下的文字。
1: 新年快樂! 2: 圣誕快樂!如果當前的語言文化為en-US,或者其它非zh-CN,頁面的文字將顯示為英文。比如,你通過如下的配置將默認的UI Culture替換成en-US,你將在頁面中得到如下的顯示。
1: <?xml version="1.0"?> 2: <configuration> 3: <system.web> 4: <globalization uiCulture="en-US" resourceProviderFactoryType="Artech.ResourceAppBlock.XmlResourceProviderFactory, Artech.ResourceAppBlock.Lib"/> 5: <compilation debug="true"/></system.web> 6: </configuration>實現結果:
1: Happy Chinese New Year! 2: Merry Christmas!實際上對于Global Resource的讀取,你可以采用更為簡潔的編程方式,就是以內聯的方式,以<%$ Resources:ClassKey, ResourceKey%>的形式直接寫在HTML中。在本例中,你可以不用編寫任何代碼,直接將HTML改成如下的形式即可。
1: <body> 2: <form id="form1" runat="server"> 3: <div> 4: <asp:Label id="LabelGreeting4NewYear" runat="server" Text="<%$ Resources:GreetingMessages, Greeting4NewYear%>" /> 5: <br/> 6: <asp:Label id="LabelGreeting4Chris" runat="server" Text="<%$ Resources:GreetingMessages, Greeting4Chris%>" /> 7: </div> 8: </form> 9: </body>五、LocalResource編程
上面演示了讀取或者綁定Global Resource的編程方式,現在來看看Local Resource。Local Resource,顧名思義,就是每個.aspx頁面對應一個獨自使用的資源文件。按照如上圖所示的結構,我為Default.aspx添加了三個本地資源文件:Default.aspx.xml、Default.aspx.zh-CN.xml和Default.aspx.en-US.xml。
由于Local Resource中的資源條沒有自動和頁面中某個控件的某個屬性進行綁定。在本例中,我們希望資源文本自定義綁定到兩個Label的Text屬性上,所以我們需要在ResourceKey中加上屬性名(Text)后綴,下面是基于英文和中文的內容。
Default.aspx.xml & Default.aspx.en-US.xml
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <add name="Greeting4Chris.Text" value="Merry Christmas!" /> 4: <add name="Greeting4NewYear.Text" value="Happy Chinese New Year!" /> 5: </resources>Default.aspx.zh-CN.xml
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <add name="Greeting4Chris.Text" value="圣誕快樂!" /> 4: <add name="Greeting4NewYear.Text" value="新年快樂!" /> 5: </resources>那么資源的綁定通過meta:resourcekey=”…” 直接寫在定義控件的HTML中即可。所以我們的Default.aspx可以進行如下的改寫,便從基于Global Resource的綁定轉變成針對Local Resource的綁定。
1: <body> 2: <form id="form1" runat="server"> 3: <div> 4: <asp:Label id="LabelGreeting4NewYear" runat="server" meta:resourcekey="Greeting4NewYear" /> 5: <br/> 6: <asp:Label id="LabelGreeting4Chris" runat="server" meta:resourcekey="Greeting4Chris" /> 7: </div> 8: </form> 9: </body>實際上,我們也可以通過代碼的方式獲取本地資源,我們只需要調用Page的GetLocalResourceObject方法即可。上面針對本地資源的綁定與下面的代碼是等效的。
1: protected void Page_Load(object sender, EventArgs e) 2: { 3: this.LabelGreeting4NewYear.Text = this.GetLocalResourceObject ("Greeting4NewYear.Text").ToString(); 4: this.LabelGreeting4Chris.Text = this.GetLocalResourceObject("Greeting4Chris.Text").ToString(); 5: }?
.NET的資源并不限于.resx文件,你可以采用任意存儲形式[上篇]
.NET的資源并不限于.resx文件,你可以采用任意存儲形式[下篇]
如何在ASP.NET應用中使用自定義資源存儲形式
作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。 原文鏈接
總結
以上是生活随笔為你收集整理的如何让ASP.NET默认的资源编程方式支持非.ResX资源存储的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis报错 Specified
- 下一篇: JSON格式提取相同属性的某个值,如何做