一起谈.NET技术,.NET的资源并不限于.resx文件,你可以采用任意存储形式 [下篇]

简介:   在《上篇》中我们谈到ResourceManager在默认的情况下只能提供对内嵌于程序集的.resources资源文件的存取。为了实现对独立二进制.resources资源文件的支持,我们自定义了BinaryResoruceNManager。

  在《上篇》中我们谈到ResourceManager在默认的情况下只能提供对内嵌于程序集的.resources资源文件的存取。为了实现对独立二进制.resources资源文件的支持,我们自定义了BinaryResoruceNManager。在本篇中我们还将创建两个自定义的ResourceManager,以实现对独立.resx资源文件和自定义结构的XML资源文件的支持。(文中的例子从这里下载)

一、自定义ResXResourceManager实现对.Resx资源文件的支持
二、将资源定义在自定义结构的XML文件中
三、为XML资源存储形式定义ResourceReader和ResourceWriter
四、为XML资源存储形式定义ResourceSet
五、为XML资源存储形式定义ResourceManager
六、补充

  一、自定义ResXResourceManager实现对.Resx资源文件的支持

  较之.resources资源文件这种二进制文件,以XML形式定义的.Resx资源文件是一个纯文本文件,我们可以对其进行自由地修改,所以有时候我们直接将独立的.resx文件作为资源存储形式更利于资源内容的维护。在《上篇》中我们创建了自定义的BinaryResourceManager实现了对独立.resources资源文件的支持,这里我们仅仅需要采用相似的方式定义一个ResXResourceManager。由于.NET已经提供了支持.Resx资源文件的ResourceSet、ResourceReader和ResourceWriter,所以ResXResourceManager和BinaryResourceManager一样简单,下面是其全部定义。

 
   
public class ResXResourceManager : FileResourceManager
{
public ResXResourceManager( string directory, string baseName)
:
base (directory, baseName, " .resx " )
{}

protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
return new ResXResourceSet( this .GetResourceFileName(culture));
}
}

  .resx文件对应的ReourceSet为ResXResourceSet,定义在System.Windows.Forms程序集中,所以在重写的InternalGetResourceSet中我们只需要返回这么一个ResXResourceSet即可。ResXResourceSet对应的ResourceReader为ResXResourceReader,而.resx文件可以通过ResXResourceWriter进行写入。

  既然我们的ResXResourceManager已经创建好了,我们就可以将它应用到我们的演示程序中。演示代码如下所示,三个辅助方法PrepareFiles、AddResource和DisplayResource的实现可以参考《上篇》,后面列出的是与之前的演示完全一样的输出结果。

 
   
PrepareFiles( " GreetingMessages " , " resx " );

AddResource(()
=> new ResXResourceWriter( " GreetingMessages.resx " ), new CultureInfo( " en-US " ));
AddResource(()
=> new ResXResourceWriter( " GreetingMessages.en-US.resx " ), new CultureInfo( " en-US " ));
AddResource(()
=> new ResXResourceWriter( " GreetingMessages.zh-CN.resx " ), new CultureInfo( " zh-CN " ));

DisplayResource(
new ResXResourceManager( "" , " GreetingMessages " ));

  输出结果:

 
 
English (United States)
Merry Christmas
!
Happy Chinese New Year
!

Chinese (Simplified, PRC)
圣诞快乐
!
新年快乐
!

Japanese (Japan)
Merry Christmas
!
Happy Chinese New Year
!

  二、将资源定义在自定义结构的XML文件中

  .Resx资源文件本质上就是一XML文件,既然.Resx文件可以作为资源文件,我们肯定可以将资源定义在我们自定义的XML文件中。由于仅仅是作为演示,我尽可能简化这个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 >

  《上篇》中讲到,.NET的资源体系包含4个重要的对象,它们分别是ResourceManager、ResourceSet、ResourceReader和ResourceWriter。要实现将自定义结构的XML作为资源文件,我们需要自定义这四个类型。

  三、为XML资源存储形式定义ResourceReader和ResourceWriter

  我定义了如下一个XmlResourceReader作为读取XML资源文件的ResourceWriter。XmlResourceReader实现接口IResourceReader,在构造函数中将资源内容从XML文件中读取出来保存在一个XmlDocument对象中。在GetEnumerator方法中将该XmlDocument得内容转换成一个Hashtable,并返回该Hashtable的Enumerator。

 
   
public class XmlResourceReader: IResourceReader
{
public XmlDocument Document { get ; private set ; }
public XmlResourceReader( string fileName)
{
this .Document = new XmlDocument();
this .Document.Load(fileName);
}
public XmlResourceReader(Stream stream)
{
this .Document = new XmlDocument();
this .Document.Load(stream);
}
public IDictionaryEnumerator GetEnumerator()
{
Dictionary
< string , string > set = new Dictionary < string , string > ();
foreach (XmlNode item in this .Document.GetElementsByTagName( " add " ))
{
set .Add(item.Attributes[ " name " ].Value, item.Attributes[ " value " ].Value);
}
return set .GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose(){}
public void Close(){}
}

  将资源内容写入XML文件的实现定义在如下一个名为XmlResourceWriter的文件中,它实现接口IResourceWriter。上面说过我们的XML仅仅提供对于纯文本内容的支持,在这里我们仅仅实现了value参数类型为string的AddResource方法。XmlResourceWriter的逻辑很简单,仅仅涉及到对于XmlDocument节点的添加和保存,所以在这里无需再多作介绍了。

 
 
ublic class XmlResourceWriter: IResourceWriter
{
public XmlDocument Document { get ; private set ; }
private string fileName;
private XmlElement root;

public XmlResourceWriter( string fileName)
{
this .fileName = fileName;
this .Document = new XmlDocument();
this .Document.AppendChild( this .Document.CreateXmlDeclaration( " 1.0 " , " utf-8 " , null ));
this .root = this .Document.CreateElement( " resources " );
this .Document.AppendChild( this .root);
}

public void AddResource( string name, byte [] value)
{
throw new NotImplementedException();
}

public void AddResource( string name, object value)
{
throw new NotImplementedException();
}

public void AddResource( string name, string value)
{
var node
= this .Document.CreateElement( " add " );
node.SetAttribute(
" name " , name);
node.SetAttribute(
" value " , value);
this .root.AppendChild(node);
}

public void Generate()
{
using (XmlWriter writer = new XmlTextWriter( this .fileName, Encoding.UTF8))
{
this .Document.WriteTo(writer);
}
}
public void Dispose(){}
public void Close() { }
}

  四、为XML资源存储形式定义ResourceSet

  ResourceReader和ResourceWriter已经创建完毕,现在我们来创建自定义的ResourceSet:XmlResorceSet。我们定义的XmlResourceReader在构造函数中被实例化,在ReadResource方法执行过程中,它将被用于完成资源内容的读取操作,读取的结果最终用于初始化该XmlResuorceSet对象。

 
   
public class XmlResourceSet : ResourceSet
{
public XmlResourceSet(Stream stream)
{
this .Reader = new XmlResourceReader(stream);
this .Table = new Hashtable();
this .ReadResources();
}
public XmlResourceSet( string fileName)
{
base .Reader = new XmlResourceReader(fileName);
base .Table = new Hashtable();
this .ReadResources();
}
public override Type GetDefaultReader()
{
return typeof (XmlResourceReader);
}
public override Type GetDefaultWriter()
{
return typeof (XmlResourceWriter);
}
}

  五、为XML资源存储形式定义ResourceManager

  最后一部自然是创建我们自定义的ResourceManager:XmlResourceManager。和之前创建的BinaryResourceManager、ResXResourceManager一样,我们只需要重写InternalGetResourceSet方法,返回相应的ResourceSet对象即可,在这里返回的自然是上面创建的XmlResourceSet。

 
   
public class XmlResourceManager: FileResourceManager
{
public XmlResourceManager( string directory, string baseName)
:
base (directory, baseName, " .xml " )
{}

protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
return new XmlResourceSet( this .GetResourceFileName(culture));
}
}

  将XmlResourceManager放进我们的演示程序,你依然可以得到一样的结果

 
   
PrepareFiles( " GreetingMessages " , " xml " );

AddResource(()
=> new XmlResourceWriter( " GreetingMessages.xml " ), new CultureInfo( " en-US " ));
AddResource(()
=> new XmlResourceWriter( " GreetingMessages.en-US.xml " ), new CultureInfo( " en-US " ));
AddResource(()
=> new XmlResourceWriter( " GreetingMessages.zh-CN.xml " ), new CultureInfo( " zh-CN " ));

DisplayResource(
new XmlResourceManager( "" , " GreetingMessages " ));

  执行结果:

 
   
English (United States)
Merry Christmas
!
Happy Chinese New Year
!

Chinese (Simplified, PRC)
圣诞快乐
!
新年快乐
!

Japanese (Japan)
Merry Christmas
!
Happy Chinese New Year
!

  六、补充

  XmlResourceManager的定义仅仅为你提供了一种实现自定义资源存储形式的解决方案,按照一样的思路,你可以采用其他的资源存储形式,比较有价值的应该是将资源内容定义在数据库表中。在分布式架构中,你甚至可以通过远程调用服务的方式来获取资源,不过在这种情况下,你应该考虑进行相应的缓存机制提升性能。

目录
相关文章
|
12天前
|
人工智能 开发框架 量子技术
【专栏】.NET 技术:驱动创新的力量
【4月更文挑战第29天】.NET技术,作为微软的开发框架,以其跨平台、开源和语言多样性驱动软件创新。它在云计算、AI/ML、混合现实等领域发挥关键作用,通过Azure、ML.NET等工具促进新兴技术发展。未来,.NET将涉足量子计算、微服务和无服务器计算,持续拓宽软件开发边界,成为创新的重要推动力。掌握.NET技术,对于开发者而言,意味着握有开启创新的钥匙。
|
12天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
12天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
12天前
|
开发框架 Cloud Native 开发者
【专栏】剖析.NET 技术的核心竞争力
【4月更文挑战第29天】本文探讨了.NET框架在软件开发中的核心竞争力:1) .NET Core实现跨平台与云原生技术的融合,支持多操作系统和容器化;2) 提升性能和开发者生产力,采用JIT、AOT优化,提供C#新特性和Roslyn编译器平台;3) 支持现代化应用架构,包括微服务和容器化,内置安全机制;4) 丰富的生态系统和社区支持,拥有庞大的开发者社区和微软的持续投入。这些优势使.NET在竞争激烈的市场中保持领先地位。
|
4月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
46 0
|
16天前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
22 0
|
2月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
32 0
|
2月前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
5 0
|
2月前
|
开发框架 前端开发 .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,然后在重定向到另
110 5
|
4月前
|
XML 前端开发 定位技术
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
30 0