如何让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应用中使用自定义资源存储形式
- linux学习第四十二篇:PHP扩展模块安装
- linux学习第四十五篇:Nginx访问日志,Nginx日志切割,静态文件不记录日志和过期时间
- 合格的配置中心应有的素养No.76
- linux学习第四十六篇:Nginx防盗链,Nginx访问控制,Nginx解析php相关配置,Nginx代理
- linux学习第四十七篇:Nginx负载均衡,ssl原理,生产ssl密钥对,Nginx配置ssl
- linux学习第四十八篇:php-fpm的pool,php-fpm慢执行日志,定义open_basedir,php-fpm进程管理
- linux学习第五十一篇:NFS介绍,NFS服务端安装配置,NFS配置选项
- linux学习第五十二篇: exportfs命令,NFS客户端问题,FTP介绍,使用vsftpd搭建ftp服务
- linux学习第五十四篇:Tomcat介绍,安装jdk,安装Tomcat
- linux学习第五十九篇:LVS DR模式搭建,keepalived lvs
- linux学习第五十四篇:配置Tomcat监听80端口,配置Tomcat的虚拟主机,Tomcat日志
- linux学习第五十六篇:集群介绍,keepalived介绍,用keepalived配置高可用集群
- linux学习第五十八篇: 负载均衡集群介绍,LVS介绍,LVS的调度算法,LVS NAT模式搭建
- Python中eval带来的潜在风险,你知道吗?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Ubuntu系统下安装ImageMagick出错的解决过程
- linux 远程控制windows系统下的程序(三种方法)
- 详解Linux上svn命令行批量操作
- 详解linux ntp服务器时间同步设置
- CentOS设置静态IP的方法总结
- ubuntu服务器上快速部署docker的方法
- centos7使用supervisor的详细教程
- Ubuntu安装PHP和PHP Nginx配置方法
- Django在Ubuntu14.04的部署方法
- ubuntu19系统及以下版本安装android studio的教程
- CentOS7升级内核kernel5.0版本
- 详解ubuntu14.04如何设置静态IP的方法
- linux安装图形化界面的操作方法
- Apache FlinkCEP 实现超时状态监控的步骤详解
- 解决Centos7下crontab+shell脚本定期自动删除文件问题