一起谈.NET技术,如何让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具有如下一个简单的结构。


<?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();
}

时间: 2024-10-27 03:41:26

一起谈.NET技术,如何让ASP.NET默认的资源编程方式支持非.ResX资源存储的相关文章

如何让ASP.NET默认的资源编程方式支持非.ResX资源存储

之前写了两篇文章<.NET资源并不限于.ResX文件>(上篇.下篇),介绍了如何通过自定义ResourceManager的方式来扩展资源的存储形式.在那篇文章中,我定义了三种基于独立文件的ResourceManager(ResXResourceManager.BinaryResourceManager和XmlResoureManager)分别实现对.ResX,.Resource和.xml三种资源文件的访问.在本篇文章中我们将实现自定义ResourceManager和ASP.NET之间的集成,让

如何让ASP.NET默认的资源编程“.NET研究”方式支持非.ResX资源存储

之前写了两篇文章<.NET资源并不限于.ResX文件>(上篇.下篇),介绍了如何通过自定义ResourceManager的方式来扩展资源的存储形式.在那篇文章中,我定义了三种基于独立文件的ResourceManager(ResXResourceManager.BinaryResourceManager和XmlResoureManager)分别实现对.ResX,.Resource和.xml三种资源文件的访问.在本篇文章中我们将实现自定义ResourceManager和ASP.NET之间的集成,让

一起谈.NET技术,深入ASP.NET 2.0的提供者模型(2)

      WebForums.NET提供者模型-一个早期的原型 相对于微软建议使用的提供者模型,Andy的提供者模型含有一些不足.一方面,WebForums.NET中提供了单个抽象基类,所有的API定义都聚集在这个类中.其负面作用在于,如果一个客户仅想定制系统的一小部分,例如用户信息的存储方式,那么他必须提供该系统中所有方法的实现.一种更好的方案是,为系统中的每一个逻辑实体创建一个抽象基类.例如,对于一个在线消息板应用程序来说,它可能需要一些类,如UsersProvider,ForumsPro

一起谈.NET技术,关于ASP.NET与CLR相互关系的一些总结

CLR(COM服务器) CLR作为一个COM服务器实现在MSCorWks.dll文件中.安装.NET Framework时,表示CLR的COM服务器被注册到Windows的注册表里. MSCorEE.dll(垫片) MSCorEE.dll的职责是判断创建何种版本的CLR. 非托管应用程序宿主调用MSCorEE.dll(shim)中CorBindToRuntimeEx函数或者另一个相似的函数来创建CLR COM的实例.      一台机器可以安装多个版本的CLR,但在机器中只有一个版本的MSCor

一起谈.NET技术,走向ASP.NET架构设计——第一章:走向设计

前言:很多做开发的人都在不断的摸索着,积极的学习,试图找出一条走向架构设计的成功法则.每当有人问起我们的职业,我们也常常在说:"软件设计".有时,我就在想:"设计",这个已经被我们嚼烂了的词,到底有多少人真正懂"设计"的含义. 自动进入IT,走在开发这条路上,就一直在不断的摸索,寻找,苦思:如何能够才能成为架构师.于是在网络上不断的收集和阅读架构设计方面的书籍和资料,到处在找一些架构师的传记,文章和甚至是采访资料..... 同时一直不断的请教自己

一起谈.NET技术,[翻译]ASP.NET MVC 3 RC 发布通告

今天早上,ASP.NET组发布了ASP.NET 3 RC版(release candidate).你们可以从这里进行下载here. ASP.NET MVC 3是个很完美的发布,增加了大量的功能改进.它可以向后兼容ASP.NET MVC V1 和 V2,可以轻易的升级你现有的项目(可以阅读发布须知,根据里面的步骤去做).你还可以通过我之前发表的博客文章来学习ASP.NET MVC 3的很多功能.  今天的ASP.NET MVC 3 RC build 包含了一些附加的功能改进(除了修正了一些bug外

一起谈.NET技术,实战ASP.NET大规模网站架构:Web加速器

大规模网站瓶颈之一就是性能问题,如何让你的网站飞速运转起来,一直是架构师和开发人员苦于思考的问题.文章将针对基于ASP.NET开发的网站交互性非实时部分进行讨论. 一.WEB加速通常有如下方案: 1.基于ASP.NET技术的页面缓存 基于ASP.NET技术的页面缓存,通常有如下两种应用方式: 一.基于数据库触发(设置缓存依赖策略,当数据库中数据发生变化时,触发缓存失效;但微软提供的解决方案目前仅支持SQL Server,如果是ORACLE需要自己实现触发接口). 二.基于文件依赖的策略(可以设置

一起谈.NET技术,跟ASP.NET MVC一起使用jQuery

藉由ASP.NET MVC内置的扩展性,开发人员便可以使用第三方库,例如jQuery.在使用ASP.NET Webforms的时候,如果使用jQuery而不是ASP.NET AJAX,难度会比较大. 刚开始撰写本文的时候,ASP.NET MVC的版本是Preview 4,有些在Preview 4中使用的技术可能无法在早期版本中正常工作.Preview 4可以在CodePlex上下载. 初步配置 我不打算把它写成一篇完整的jQuery指南,只是简单给出几个跟ASP.NET MVC一起使用这款Jav

一起谈.NET技术,提高ASP.NET应用程序性能的十大方法

一.返回多个数据集 检查你的访问数据库的代码,看是否存在着要返回多次的请求.每次往返降低了你的应用程序的每秒能够响应请求的次数.通过在单个数据库请求中返回多个结果集,可以减少与数据库通信的时间,使你的系统具有扩展性,也可以减少数据库服务器响应请求的工作量. 如果你是用动态的SQL语句来返回多个数据集,那我建议你用存储过程来替代动态的SQL语句.是否把业务逻辑写到存储过程中,这个有点争议.但是我认为,把业务逻辑写到存储过程里面可以限制返回结果集的大小,减小网络数据的流量,在逻辑层也不用在过滤数据,