如何讓ASP.NET默認的資源編程方式支持非.ResX資源存儲

作者: Artech  來源: 博客園  發布時間: 2011-01-07 10:52  閱讀: 1058 次  推薦: 0   原文鏈接   [收藏]  

  之前寫了兩篇文章《.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具有如下一個簡單的結構。

 
<?xml version="1.0" encoding="utf-8"?>
<resources>
<add name="Greeting4Chris" value="Merry Christmas!" />
<add name="Greeting4NewYear" value="Happy Chinese New Year!" />
</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。

 
public class XmlResourceProvider:IResourceProvider
{

public XmlResourceManager ResourceManager { get; private set; }
public XmlResourceProvider(string directory, string baseName)
{

this.ResourceManager = new XmlResourceManager(directory, baseName);
}


public object GetObject(string resourceKey, CultureInfo culture)
{

return this.ResourceManager.GetObject(resourceKey, culture);
}


public IResourceReader ResourceReader
{

get
{
return new XmlResourceReader(Path.Combine(this.ResourceManager.Directory,this.ResourceManager.BaseName+".xml"));
}
}

  三、創建自定義ResourceProviderFactory

  XmlResourceProvider創建完畢,但是它不能直接被注冊,我們需要創建一個對應的工廠類。為此,如下一個名稱為XmlResourceProviderFactory類被創建出來。

 
public class XmlResourceProviderFactory:ResourceProviderFactory
{

public override IResourceProvider CreateGlobalResourceProvider(string classKey)
{

string directory = HttpContext.Current.Server.MapPath("GlobalResources");
return new XmlResourceProvider(directory, classKey);
}


public override IResourceProvider CreateLocalResourceProvider(string virtualPath)
{

string directory = HttpContext.Current.Server.MapPath(VirtualPathUtility.GetDirectory(virtualPath));
string baseName = VirtualPathUtility.GetFileName(virtualPath);
return new XmlResourceProvider(directory, baseName);
}
}

  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>配置節進行注冊,下面是相應的配置。

 
<?xml version="1.0"?>
<configuration>
<system.web>
<globalization uiCulture="zh-CN" resourceProviderFactoryType="Artech.ResourceAppBlock.XmlResourceProviderFactory, Artech.ResourceAppBlock.Lib"/>
<compilation debug="true"/></system.web>
</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具有相同的內容。

 
<?xml version="1.0" encoding="utf-8"?>
<resources>
<add name="Greeting4Chris" value="Merry Christmas!" />
<add name="Greeting4NewYear" value="Happy Chinese New Year!" />
</resources>

  而GreetingMessages.zh-CN.xml則為中文。

 
<?xml version="1.0" encoding="utf-8"?>
<resources>
<add name="Greeting4Chris" value="圣誕快樂!" />
<add name="Greeting4NewYear" value="新年快樂!" />
</resources>

  現在我們創建一個文件名稱為Defualt.aspx的Web頁,并在其中放置兩個Label控件相應的HTML如下所示。

 
<body>
<form id="form1" runat="server">
<div>
<asp:Label id="LabelGreeting4NewYear" runat="server" />
<br/>
<asp:Label id="LabelGreeting4Chris" runat="server"/>
</div>
</form>
</body>

  在Page加載的時候,通過如下的代碼將兩個Label和相應的資源條目進行綁定。

 
protected void Page_Load(object sender, EventArgs e)
{

this.LabelGreeting4NewYear.Text = this.GetGlobalResourceObject("GreetingMessages", "Greeting4NewYear").ToString();
this.LabelGreeting4Chris.Text = this.GetGlobalResourceObject("GreetingMessages", "Greeting4Chris").ToString();
}

  在瀏覽器中訪問頁面,你會得到如下的文字。

 
新年快樂!
圣誕快樂!

  如果當前的語言文化為en-US,或者其它非zh-CN,頁面的文字將顯示為英文。比如,你通過如下的配置將默認的UI Culture替換成en-US,你將在頁面中得到如下的顯示。

 
<?xml version="1.0"?>
<configuration>
<system.web>
<globalization uiCulture="en-US" resourceProviderFactoryType="Artech.ResourceAppBlock.XmlResourceProviderFactory, Artech.ResourceAppBlock.Lib"/>
<compilation debug="true"/></system.web>
</configuration>

  實現結果:

 
Happy Chinese New Year!
Merry Christmas!

  實際上對于Global Resource的讀取,你可以采用更為簡潔的編程方式,就是以內聯的方式,以<%$ Resources:ClassKey, ResourceKey%>的形式直接寫在HTML中。在本例中,你可以不用編寫任何代碼,直接將HTML改成如下的形式即可。

 
<body>
<form id="form1" runat="server">
<div>
<asp:Label id="LabelGreeting4NewYear" runat="server" Text="<%$ Resources:GreetingMessages, Greeting4NewYear%>" />
<br/>
<asp:Label id="LabelGreeting4Chris" runat="server" Text="<%$ Resources:GreetingMessages, Greeting4Chris%>" />
</div>
</form>
</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

 
<?xml version="1.0" encoding="utf-8"?>
<resources>
<add name="Greeting4Chris.Text" value="Merry Christmas!" />
<add name="Greeting4NewYear.Text" value="Happy Chinese New Year!" />
</resources>

  Default.aspx.zh-CN.xml

 
<?xml version="1.0" encoding="utf-8"?>
<resources>
<add name="Greeting4Chris.Text" value="圣誕快樂!" />
<add name="Greeting4NewYear.Text" value="新年快樂!" />
</resources>

  那么資源的綁定通過meta:resourcekey=”…” 直接寫在定義控件的HTML中即可。所以我們的Default.aspx可以進行如下的改寫,便從基于Global Resource的綁定轉變成針對Local Resource的綁定。

 
<body>
<form id="form1" runat="server">
<div>
<asp:Label id="LabelGreeting4NewYear" runat="server" meta:resourcekey="Greeting4NewYear" />
<br/>
<asp:Label id="LabelGreeting4Chris" runat="server" meta:resourcekey="Greeting4Chris" />
</div>
</form>
</body>

  實際上,我們也可以通過代碼的方式獲取本地資源,我們只需要調用Page的GetLocalResourceObject方法即可。上面針對本地資源的綁定與下面的代碼是等效的。

 
protected void Page_Load(object sender, EventArgs e)
{

this.LabelGreeting4NewYear.Text = this.GetLocalResourceObject ("Greeting4NewYear.Text").ToString();
this.LabelGreeting4Chris.Text = this.GetLocalResourceObject("Greeting4Chris.Text").ToString();
}

0
0
 
標簽:ASP.NET
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()