在.NET框架中,配置文件的反序列化是一个常见的需求。自.NET 2.0发布以来,旧的IConfigurationSectionHandler
接口已经被弃用,取而代之的是一系列新的类和属性。主要的替代类是ConfigurationElement
,但是大多数示例只演示了如何处理带有属性数据的XML。本文将介绍如何反序列化包含文本内容的XML元素。
在.NET2.0之前,可以使用IConfigurationSectionHandler
接口来反序列化所有类型的配置XML。自.NET2.0发布以来,该接口已被弃用,取而代之的是一系列新的类和属性。虽然大多数XML可以重写为将文本内容移动到属性中,但这样做会丢失XML本身的一些表达能力。
在开始之前,需要引用并包含以下命名空间:
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
所有示例类都在以下命名空间定义中编写:
namespace ConfigurationTextElement
{
}
向项目的主配置文件添加自定义节。在这个示例中,项目的命名空间和程序集名为ConfigurationTextElement
。自定义节名为root
,并将存储在名为root.config
的文件中。
如果选择将根XML存储在单独的文件中,请确保将文件的Copy to Output Directory
属性更改为Copy Always
。这将确保在调试期间使用的二进制文件夹中存在该文件。
第一个类将对应于根元素,它也代表配置节。
using System.Configuration;
public class Root : ConfigurationSection
{
}
创建一个懒单例类,它在静态属性中公开根类的实例。在这个示例中,配置类将直接被应用程序使用。
using System.Configuration;
namespace ConfigurationTextElement
{
public class Settings
{
private static Root _root = null;
private Settings() { }
public static Root Root
{
get
{
if (_root == null)
{
_root = (Root)ConfigurationManager.GetSection("root");
}
return _root;
}
}
}
}
创建将存储element1
的类,添加适当的基类和属性属性。
public class Element1 : ConfigurationElement
{
[ConfigurationProperty("attrib1")]
public String Attrib1
{
get
{
return this["attrib1"].ToString();
}
}
[ConfigurationProperty("attrib2")]
public String Attrib2
{
get
{
return this["attrib2"].ToString();
}
}
}
更新根类以包括element1
的属性。
public class Root : ConfigurationSection
{
[ConfigurationProperty("element1")]
public Element1 Element1
{
get
{
return (Element1)this["element1"];
}
}
}
在页面或窗体的OnLoad
方法中添加代码以测试attrib1
和attrib2
的值。
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string e1a1;
e1a1 = Settings.Root.Element1.Attrib1;
}
上述元素相对容易实现,与许多其他可用示例非常相似。下一个元素element2
则不那么直接。实际上,尝试使用ConfigurationElement
反序列化它将产生以下错误:
配置节不能包含CDATA或文本元素。
创建一个名为ConfigurationTextElement
的新类,该类是泛型的,继承自ConfigurationElement
,并覆盖其基类的DeserializeElement
方法。这个类也是一个泛型类,根据实例化时指定的类型将数据转换并返回。
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
public class ConfigurationTextElement : ConfigurationElement
{
private T _value;
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
_value = (T)reader.ReadElementContentAs(typeof(T), null);
}
public T Value
{
get
{
return _value;
}
}
}
public class Root : ConfigurationSection
{
[ConfigurationProperty("element1")]
public Element1 Element1
{
get
{
return (Element1)this["element1"];
}
}
[ConfigurationProperty("element2")]
public ConfigurationTextElement Element2
{
get
{
return (ConfigurationTextElement)this["element2"];
}
}
[ConfigurationProperty("element3")]
[ConfigurationCollection(typeof(Child1), AddItemName = "child1")]
public Element3 Element3
{
get
{
return (Element3)this["element3"];
}
}
[ConfigurationProperty("element4")]
[ConfigurationCollection(typeof(ConfigurationTextElement), AddItemName = "child2")]
public Element4 Element4
{
get
{
return (Element4)this["element4"];
}
}
}
public class Element1 : ConfigurationElement
{
[ConfigurationProperty("attrib1")]
public String Attrib1
{
get
{
return this["attrib1"].ToString();
}
}
[ConfigurationProperty("attrib2")]
public String Attrib2
{
get
{
return this["attrib2"].ToString();
}
}
}
public class Element3 : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new Child1();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Child1)element).Key;
}
public Child1 this[int index]
{
get
{
return (Child1)BaseGet(index);
}
}
new public Child1 this[string key]
{
get
{
return (Child1)BaseGet(key);
}
}
public bool ContainsKey(string key)
{
List
public class Element4 : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new ConfigurationTextElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ConfigurationTextElement)element).Value;
}
public ConfigurationTextElement this[int index]
{
get
{
return (ConfigurationTextElement)BaseGet(index);
}
}
}
public class Child1 : ConfigurationElement
{
[ConfigurationProperty("key")]
public String Key
{
get
{
return this["key"].ToString();
}
}
[ConfigurationProperty("value")]
public String Value
{
get
{
return this["value"].ToString();
}
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string e1a1;
string e2;
string e3c1_item1;
string e3c1_item2;
string e4c2_item1;
string e4c2_item2;
e1a1 = Settings.Root.Element1.Attrib1;
e2 = Settings.Root.Element2.ToString();
e3c1_item1 = Settings.Root.Element3[0].Value;
e3c1_item2 = Settings.Root.Element3["y"].Value;
e4c2_item1 = Settings.Root.Element4[0].Value;
e4c2_item2 = Settings.Root.Element4[1].Value;
}