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

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

  之前写了两篇文章《.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();
}

目录
相关文章
|
6月前
|
存储 开发框架 前端开发
asp.net与asp.net优缺点及示例
asp.net与asp.net优缺点及示例
|
30天前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
28 0
|
1月前
|
开发框架 中间件 .NET
C# .NET面试系列七:ASP.NET Core
## 第一部分:ASP.NET Core #### 1. 如何在 controller 中注入 service? 在.NET中,在ASP.NET Core应用程序中的Controller中注入服务通常使用<u>依赖注入(Dependency Injection)</u>来实现。以下是一些步骤,说明如何在Controller中注入服务: 1、创建服务 首先,确保你已经在应用程序中注册了服务。这通常在Startup.cs文件的ConfigureServices方法中完成。例如: ```c# services.AddScoped<IMyService, MyService>(); //
60 0
|
1月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
95 5
|
3月前
|
开发框架 安全 搜索推荐
分享105个NET源码ASP源码,总有一款适合您
分享105个NET源码ASP源码,总有一款适合您
27 4
|
5月前
|
存储 SQL 监控
.NET开源简单易用、内置集成化的控制台、支持持久性存储的任务调度框架 - Hangfire
.NET开源简单易用、内置集成化的控制台、支持持久性存储的任务调度框架 - Hangfire
|
6月前
|
开发框架 .NET 数据库
asp.net企业费用报销管理信息系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
asp.net 企业费用报销管理信息系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使 用c#语言开发 应用技术:asp.net c#+sqlserver 开发工具:vs2010 +sqlserver
49 0
|
7月前
|
开发框架 前端开发 .NET
.NET 8 Release Candidate 1 (RC1)现已发布,包括许多针对ASP.NET Core的重要改进!
.NET 8 Release Candidate 1 (RC1)现已发布,包括许多针对ASP.NET Core的重要改进!
174 0
.NET 8 Release Candidate 1 (RC1)现已发布,包括许多针对ASP.NET Core的重要改进!
|
9月前
|
开发框架 前端开发 JavaScript
ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件
ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件
|
10月前
|
开发框架 供应链 前端开发
net基于asp.net的社区团购网站
社区团购系统依托社区团购系统和社区门店,是现在的一个重大市场和发展方向,通过研究企业在社区团购系统环境下的营销模式创新,对于普通的零售业和传统社区团购系统的转型发展具有重要的理论意义。随着互联网行业的发展,人们的生活方式发生着重大变化,人们越来越倾向于网络购物,这对传统企业来说如何把客户留下是一个重大挑战。就现在而言,由于社区团购的竞争已经进入最紧张激烈的阶段,有些团购平台甚至已经彼此之间打起了价格战,其中不乏有平台因为利润变少或资金链断裂而半途败亡。企业在实际的商业活动中,往往会面临许多等待优化的问题。因此,要在竞争激烈的市场中拔得头筹,必须重视提升对新商业模式的全面认知,科学于实际贴合的分