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

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

时间: 2024-11-10 07:50:34

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

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

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

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

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

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

为了构建一个轻量级的资源管理框架以满足简单的本地化(Localization)的需求,我试图直接对现有的Resource编程模型进行扩展.虽然最终没能满足我们的需求,但是这两天也算对.NET如何进行资源的存取进行了深入的学习,所以将我对此的认识通过博文的方式与诸位分享.在本篇文章中,我会通过自定义ResourceManager让资源的存储形式不仅仅局限于.ResX文件,你可以根据需要实现任意的存储方式,比如结构化的XML.数据库表,甚至是通过远程访问获取资源.(文中的例子从这里下载) 一.从添加

区域-C# 资源文件Resource .resx文件多语言无法编译。

问题描述 C# 资源文件Resource .resx文件多语言无法编译. 如图,只有默认资源ISOResour.resx能够附加进DLL中,而zh-CN,zh-TW,都无法编译进DLL resx的路径应该是正确的,因为默认的资源文件是能够读取的,只是加了CultureInfo进去了过后 就会报错, 未能找到任何适合于指定的区域性或非特定区域性的资源.------ 解决方案 这个资源有专门的文件路径存放的.如图,右键项目

sivlerlight绑定资源Resx文件里的字符串问题

sivlerlight绑定资源Resx文件里的字符串时,请把资源中访问修饰符设置为Public,同时把构造方法改为Public.

如何改变Resx文件中的值

我们在开发程序时,有时会将一些值存放于resx文件中,但想要改变它的值怎么办呢?例子如我在全局 资源(App_GlobalResources)中建立了一个资源文件Resource.resx.并建了两个String值,Anm_Response 和Rqi_Response. 我们可以录入进去,但如何在程序中改呢? 其实Resx文件是一个XML文件.被存放在名为"data"的结点中.如下边文档: <data name="Anm_Response" xml:space

resx文件在X64位编译,提示“未能加载文件或程序集”的问题?

原文:resx文件在X64位编译,提示"未能加载文件或程序集"的问题? resx文件在X64位编译,提示"未能加载文件或程序集"的问题? 解答: 错误现象如下 此问题最多在VS2010或者(SP1)上出现过,属于VS2010的缺陷,估计在VS更高的版本不会出现此问题. 通常提示: <dataname="imageCollection1.ImageStream" type="xxxxxx"mimetype="ap

Resx 文件无效,未能加载 .RESX 文件中使用的类型

错误信息提示: 错误 339 Resx 文件无效.未能加载 .RESX 文件中使用的类型 Forms.ListItems, Forms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.请确保已在项目中添加了必需的引用. 第 136 行,位置 5. E:\Forms\Form2.resx 136 5 Forms <?xml version="1.0" encoding="utf-8"?> <

csdn-请问CSDN下载到“我的资源“里“下载资源“的文件, 要如何使用?

问题描述 请问CSDN下载到"我的资源"里"下载资源"的文件, 要如何使用? 请问CSDN下载到"我的资源"里"下载资源"的文件, 要如何使用? 在列表中有出现该文檔, 但是点选它都没有用, 请问是放在云端还是可以 下载到当本地硬盘里?谢谢! 解决方案 csdn有bug,多下几次就可以了.建议使用IE Chrome.不要用国产山寨浏览器,另外检查下电脑有没有感染360等病毒. 解决方案二: 有些文档是只能在线看的 解决方案三: