在一次升级一个entlib1.0到entlib的高版本程序时,碰到entlib的一个通过XmlSerializer方式实现的自定义配置。而在entlib的高版本中这样的配置不再被支持。可是又不希望修改相应的配置类的接口,避免引起大规模的关联修改。在查阅相关资料并且测试之后,找了些可以操作的方法,可以分别通过IConfigSectionHandler和ConfigSection继承来实现。
具体的实现方式:
(1) 类定义:
首先我们定义一个自定义配置的类,其中有我们在程序中需要的相关配置信息。
public class MyObject
{
private int myInt;
public int MyInt
{
get { return myInt; }
set { myInt = value; }
}
private string myStr;
public string MyStr
{
get { return myStr; }
set { myStr = value; }
}
}
然后有一个与之相应的串行化xml文件,在经过反串行化化后可以得到一个MyObject的对象。在串行化的过程中,需要注意的是,如果String属性没有被赋值的话,不会出现在串行化数据文件中。文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyInt>1</MyInt>
<MyStr>string 1</MyStr>
</MyObject>
设置配置文件:
然后我们设定其配置文件,在配置文件中,我们通过configSource属性指定扩展的配置文件,当然也可以把外部文件的内容放在配置文字中,不过出于配置文件独立性和可读性的考虑,还是考虑放在外部的配置文件中好些。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name=" MyObject" type="XmlSerializerDemo.YourConfigSection,XmlSerializerDemo"/>
</configSections>
<MyObject configSource="MyObject.xml"></ServerSettings>
</configuration>
(2) 通过IConfigSectionHandler实现及调用
IConfigurationSectionHandler是asp.net提供一个实现自定义配置的接口,通过实现该接口,从而实现自定义配置,在该接口中Create方法可以获得一个XmlNode的section对象,该对象为配置文件中对应的section节点的完整的xmlNode节点数据,通过对该xmlNode操作,可以方便的反串行化出相应的配置节点对象。而且Create方法可以直接返回我们需要的对象,而不必通过ConfigSect的方式间接获得。
代码实现:
public class YourConfigSection: IConfigurationSectionHandler
{
#region IConfigurationSectionHandler 成员
public object Create(object parent, object configContext, System.Xml.XmlNode section)
{
XmlSerializer xs = new XmlSerializer(typeof(MyObject));
XmlNodeReader xr = new XmlNodeReader(section);
object obj = xs.Deserialize(xr);
xr.Close();
return obj;
}
#endregion
}
调用例子:
MyObject myobj = (MyObject)System.Configuration.ConfigurationManager.GetSection(“ServerSettings”);
(3) 通过ConfigSection实现及调用
通过ConfigSection的扩展实现是asp.net2.0推荐的自定义配置实现方式,而通过IConfigurationSectionHandler实现的配置方式将不再被推荐。考虑到向后的兼容性,实现一个通过ConfigSection实现的配置还是有必要的。在ConfigUration的DeserializeSection方法中,会有一个XmlReader的对象,如果XmlReader中流正好就是我们需要的串行化对象时,可以通过直接反串行化获得我们需要的对象,不过这样一来就严格要求在XmlReader中的流数据一定要正好是我们需要的串行化对象数据,而不能包括其他的xml层次信息,当然也可以通过XmlReader进一步提取需要的数据信息,但那样可能增加了不必要的操作。
代码实现:
public class YourConfigSection:System.Configuration.ConfigurationSection
{
private MyObject myObj;
public MyObject MyConfig
{
get { return myObj; }
}
protected override void DeserializeSection(System.Xml.XmlReader reader)
{
XmlSerializer xs = new XmlSerializer(typeof(MyObject));
myObj = xs.Deserialize(reader) as MyObject;
}
调用例子:
YourConfigSection section = (YourConfigSection)
System.Configuration.ConfigurationManager.GetSection(“ServerSettings”);
MyObject myobj = section.MyConfig;