.NET的资源并不限于.resx文件,你可以采用任意存储“.NET研究”形式 [下篇]

简介:   在《上篇》中我们谈到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上海徐汇企业网站制作an>");

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 NotImplementedE上海企业网站设计与制作xception();
}

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

public void上海网站建设an> AddResource(string name, string value)
{
var node
= this.Document.CreateElement(上海企业网站制作>"add");
node.SetAttribute(
"name", name);
node.SetAttribute(
"value", value);
this.root.AppendChild(node);
}

上海闵行企业网站设计与制作"color: #0000ff;">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的定义仅仅为你提供了一种实现自定义资源存储形式的解决方案,按照一样的思路,你可以采用其他的资源存储形式,比较有价值的应该是将资源内容定义在数据库表中。在分布式架构中,你甚至可以通过远程调用服务的方式来获取资源,不过在这种情况下,你应该考虑进行相应的缓存机制提升性能。

目录
相关文章
|
5天前
|
存储 对象存储 Python
`openpyxl`是一个用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件的Python库。它不需要Microsoft Excel,也不需要.NET或COM组件。
`openpyxl`是一个用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件的Python库。它不需要Microsoft Excel,也不需要.NET或COM组件。
|
12天前
|
算法 API 数据安全/隐私保护
.NET使用原生方法实现文件压缩和解压
.NET使用原生方法实现文件压缩和解压
.NET使用原生方法实现文件压缩和解压
|
12天前
|
存储 C#
.NET使用CsvHelper快速读取和写入CSV文件
.NET使用CsvHelper快速读取和写入CSV文件
|
1月前
|
机器学习/深度学习 JSON 测试技术
CNN依旧能战:nnU-Net团队新研究揭示医学图像分割的验证误区,设定先进的验证标准与基线模型
在3D医学图像分割领域,尽管出现了多种新架构和方法,但大多未能超越2018年nnU-Net基准。研究发现,许多新方法的优越性未经严格验证,揭示了验证方法的不严谨性。作者通过系统基准测试评估了CNN、Transformer和Mamba等方法,强调了配置和硬件资源的重要性,并更新了nnU-Net基线以适应不同条件。论文呼吁加强科学验证,以确保真实性能提升。通过nnU-Net的变体和新方法的比较,显示经典CNN方法在某些情况下仍优于理论上的先进方法。研究提供了新的标准化基线模型,以促进更严谨的性能评估。
69 0
|
1月前
|
存储 安全 Unix
【.Net Core】深入理解IO之文件和目录
【.Net Core】深入理解IO之文件和目录
34 4
|
22天前
|
存储 C#
.NET使用CsvHelper快速读取和写入CSV文件
优秀项目和框架精选 该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。
|
1月前
|
存储 分布式计算 大数据
MaxCompute操作报错合集之自定义udf的函数,引用了import net.sourceforge.pinyin4j.PinyinHelper;但是上传资源后,出现报错,是什么原因
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
1月前
|
开发框架 .NET Linux
【.NET Developer】已发布好的.NET Core项目文件如何打包为Docker镜像文件
该文介绍了如何不使用VS2019手动创建ASP.NET Core Blazor项目的Dockerfile并构建Docker镜像。首先,创建名为Dockerfile的文件,并复制提供的Dockerfile内容,该文件指定了基础镜像和工作目录。然后,通过CMD在项目目录下运行`docker build -t 自定义镜像名 .`来生成镜像。最后,使用`docker run`命令启动容器并验证项目运行。此外,文章还提到了将镜像推送到Azure Container Registry (ACR)的步骤。
|
2月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
115 0
|
2月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
44 0