一起谈.NET技术,.NET的资源并不限于.resx文件,你可以采用任意存储形式 [下篇]
2011-09-02 00:18
489 查看
在《上篇》中我们谈到ResourceManager在默认的情况下只能提供对内嵌于程序集的.resources资源文件的存取。为了实现对独立二进制.resources资源文件的支持,我们自定义了BinaryResoruceNManager。在本篇中我们还将创建两个自定义的ResourceManager,以实现对独立.resx资源文件和自定义结构的XML资源文件的支持。(文中的例子从这里下载)
一、自定义ResXResourceManager实现对.Resx资源文件的支持
二、将资源定义在自定义结构的XML文件中
三、为XML资源存储形式定义ResourceReader和ResourceWriter
四、为XML资源存储形式定义ResourceSet
五、为XML资源存储形式定义ResourceManager
六、补充
[/code]
.resx文件对应的ReourceSet为ResXResourceSet,定义在System.Windows.Forms程序集中,所以在重写的InternalGetResourceSet中我们只需要返回这么一个ResXResourceSet即可。ResXResourceSet对应的ResourceReader为ResXResourceReader,而.resx文件可以通过ResXResourceWriter进行写入。
既然我们的ResXResourceManager已经创建好了,我们就可以将它应用到我们的演示程序中。演示代码如下所示,三个辅助方法PrepareFiles、AddResource和DisplayResource的实现可以参考《上篇》,后面列出的是与之前的演示完全一样的输出结果。
[/code]
输出结果:
[/code]
《上篇》中讲到,.NET的资源体系包含4个重要的对象,它们分别是ResourceManager、ResourceSet、ResourceReader和ResourceWriter。要实现将自定义结构的XML作为资源文件,我们需要自定义这四个类型。
[/code]
将资源内容写入XML文件的实现定义在如下一个名为XmlResourceWriter的文件中,它实现接口IResourceWriter。上面说过我们的XML仅仅提供对于纯文本内容的支持,在这里我们仅仅实现了value参数类型为string的AddResource方法。XmlResourceWriter的逻辑很简单,仅仅涉及到对于XmlDocument节点的添加和保存,所以在这里无需再多作介绍了。
[/code]
[/code]
将XmlResourceManager放进我们的演示程序,你依然可以得到一样的结果
[/code]
执行结果:
[/code]
一、自定义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一样简单,下面是其全部定义。[code] [code]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)); } }
[/code]
.resx文件对应的ReourceSet为ResXResourceSet,定义在System.Windows.Forms程序集中,所以在重写的InternalGetResourceSet中我们只需要返回这么一个ResXResourceSet即可。ResXResourceSet对应的ResourceReader为ResXResourceReader,而.resx文件可以通过ResXResourceWriter进行写入。
既然我们的ResXResourceManager已经创建好了,我们就可以将它应用到我们的演示程序中。演示代码如下所示,三个辅助方法PrepareFiles、AddResource和DisplayResource的实现可以参考《上篇》,后面列出的是与之前的演示完全一样的输出结果。
[code] [code]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"));
[/code]
输出结果:
[code]<?xml version="1.0" encoding="utf-8"?> <resources> <add name="Greeting4Chris" value="Merry Christmas!" /> <add name="Greeting4NewYear" value="Happy Chinese New Year!" /> </resources>
[/code]
《上篇》中讲到,.NET的资源体系包含4个重要的对象,它们分别是ResourceManager、ResourceSet、ResourceReader和ResourceWriter。要实现将自定义结构的XML作为资源文件,我们需要自定义这四个类型。
三、为XML资源存储形式定义ResourceReader和ResourceWriter
我定义了如下一个XmlResourceReader作为读取XML资源文件的ResourceWriter。XmlResourceReader实现接口IResourceReader,在构造函数中将资源内容从XML文件中读取出来保存在一个XmlDocument对象中。在GetEnumerator方法中将该XmlDocument得内容转换成一个Hashtable,并返回该Hashtable的Enumerator。[code] [code]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(){} }
[/code]
将资源内容写入XML文件的实现定义在如下一个名为XmlResourceWriter的文件中,它实现接口IResourceWriter。上面说过我们的XML仅仅提供对于纯文本内容的支持,在这里我们仅仅实现了value参数类型为string的AddResource方法。XmlResourceWriter的逻辑很简单,仅仅涉及到对于XmlDocument节点的添加和保存,所以在这里无需再多作介绍了。
[code]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); } }
[/code]
五、为XML资源存储形式定义ResourceManager
最后一部自然是创建我们自定义的ResourceManager:XmlResourceManager。和之前创建的BinaryResourceManager、ResXResourceManager一样,我们只需要重写InternalGetResourceSet方法,返回相应的ResourceSet对象即可,在这里返回的自然是上面创建的XmlResourceSet。[code] [code]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)); } }
[/code]
将XmlResourceManager放进我们的演示程序,你依然可以得到一样的结果
[code] [code]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"));
[/code]
执行结果:
[code] [code]English (United States) Merry Christmas! Happy Chinese New Year! Chinese (Simplified, PRC) 圣诞快乐! 新年快乐! Japanese (Japan) Merry Christmas! Happy Chinese New Year!
[/code]
六、补充
XmlResourceManager的定义仅仅为你提供了一种实现自定义资源存储形式的解决方案,按照一样的思路,你可以采用其他的资源存储形式,比较有价值的应该是将资源内容定义在数据库表中。在分布式架构中,你甚至可以通过远程调用服务的方式来获取资源,不过在这种情况下,你应该考虑进行相应的缓存机制提升性能。相关文章推荐
- 一起谈.NET技术,.NET的资源并不限于.resx文件,你可以采用任意存储形式 [上篇]
- .NET的资源并不限于.resx文件,你可以采用任意存储“.NET研究”形式 [下篇]
- .NET的资源并不限于.resx文件,你可以采用任意存储形式[下篇]
- .NET的资源并不限于.resx文件,你可以采用任意存储形式[下篇]
- .NET的资源并不限于.resx文件,你可以采用任意存储形式[上篇]
- .NET的资源并“.NET研究”不限于.resx文件,你可以采用任意存储形式 [上篇]
- 一起谈.NET技术,如何让ASP.NET默认的资源编程方式支持非.ResX资源存储
- .Net下二进制形式的文件(图片)的存储与读取
- 一起谈.NET技术,模拟IIS向Silverlight输出策略文件
- 一起谈.NET技术,创建代码生成器可以很简单:如何通过T4模板生成代码?[上篇]
- 一起谈.NET技术,从数据到代码—通过代码生成机制实现强类型编程[下篇]
- 一起谈.NET技术,探索Asp.net mvc 的文件上传(由浅入深)
- 一起谈.NET技术,Xml日志记录文件最优方案(附源代码)
- .Net下二进制形式的文件(图片)的存储与读取
- .NET 资源文件resx、Resources详细说明
- 一起谈.NET技术,.net其实也可以不拖控件的......
- 一起谈.NET技术,WCF使用NetTcp传输文件
- 一起谈.NET技术,创建代码生成器可以很简单:如何通过T4模板生成代码?[下篇]
- 什么是序列化?一句话:就是将java对象固化成文件存起来,这样就java对象就被固话了,可以任意的存储和网络传输了,而java对象是暂时存在内存里的,是没办法传输的,因为是虚拟的,并不是实实在在的文件
- 一起谈.NET技术,ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇]