博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何让ASP.NET默认的资源编程“.NET研究”方式支持非.ResX资源存储
阅读量:6908 次
发布时间:2019-06-27

本文共 7362 字,大约阅读时间需要 24 分钟。

  之前写了两篇文章《.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
>
上海徐汇企业网站制作an><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"
/>
<
上海闵行企业网站设计与制作tyle="color: #800000;">br
/>
<
asp:Label
id
="LabelGreeting4Chris"
runat
="server"
meta:resourcekey 上海企业网站制作"color: #0000ff;">="Greeting4Chris"
/>
</上海闵行企业网站制作an>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();
}

转载地址:http://angdl.baihongyu.com/

你可能感兴趣的文章
Redis有序集合类型
查看>>
Codepen 每周精选:不能错过的23个页面特效(2018-5-14)
查看>>
webstorm+chrome+eggjs进行断点调试
查看>>
React GraphQL Koa仿Pinterest手机端
查看>>
为容器安全苦恼?这份清单整理了27种容器安全工具
查看>>
来聊聊怎么写react-native上的样式吧
查看>>
XPath与lxml类库
查看>>
前端面试题-BFC(块格式化上下文)
查看>>
CSS Grid 系列(下)-使用Grid布局构建网站首页
查看>>
2017中国云计算评测报告
查看>>
【339天】我爱刷题系列098(2018.01.10)
查看>>
结合 CSS3 transition transform 实现简单的跑马灯效果
查看>>
原生js系列之DOM工厂模式
查看>>
使用babel将es6语法转es5
查看>>
Python Apscheduler源代码解析(一) 任务调度流程
查看>>
Just for fun——windows上bat管理你的Nginx+PHP+MySQL
查看>>
Spring Boot 中使用 SolrCloud
查看>>
浅谈vue的Class 与 Style 绑定
查看>>
Spring Boot之 Servlet、Fiter、Listener的使用
查看>>
MySQL学习记录:子查询与连接
查看>>