曾写过一篇文章ConfigurationSettings相关 使用了比较笨的方法来写ConfigurationSectionHandler的Create方法,后来知道可以利用XmlNode的反序列化时,我才明白原来可以更聪明一些。当然还要搞明白在一些XML序列化标记Attribute。
还以原文的配置XML来说明,不过我打算让他看起来舒服一些,改变如xml-content-001:
xml-content-001
<jobsSettings>
<job interval="0" workAt="03:00">
<WorkBy>Mag.HtmlCache.HtmlDo,Mag.Web</WorkBy>
</job>
<job interval="0" workAt="04:00">
<WorkBy>Mag.HtmlCache.HtmlClear,Mag.Web</WorkBy>
</job>
</jobsSettings>
谁来处理我定义的这段配置节点呢?xml-content-002指明是Mag.MainSrv.JobSettingSectionHandler类
xml-content-002
<configSections>
<section name="jobsSettings" type="Mag.MainSrv.JobSettingSectionHandler, Mag.MainSrv" />
</configSections>
以下是一个完整的app.config,xml-content-003:
Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="jobsSettings" type="Mag.MainSrv.JobSettingSectionHandler, Mag.MainSrv" />
</configSections>
<appSettings>
<!--一些add key= value=-->
</appSettings>
<jobsSettings>
<job interval="0" workAt="03:00">
<WorkBy>Mag.HtmlCache.HtmlDo,Mag.Web</WorkBy>
</job>
<job interval="0" workAt="04:00">
<WorkBy>Mag.HtmlCache.HtmlClear,Mag.Web</WorkBy>
</job>
</jobsSettings>
</configuration>
Mag.MainSrv.JobSettingSectionHandler是一个实现了System.Configuration.IConfigurationSectionHandler接口的类,IConfigurationSectionHandler接口只有方法Create,以下是反序的过程
Code001
public object Create(object parent, object configContext, System.Xml.XmlNode section)
{
JobsManager manger = null;
using (System.Xml.XmlNodeReader sr = new System.Xml.XmlNodeReader(section))
{
XmlSerializer xz = new XmlSerializer(typeof(JobsManager));
manger = (ConnectManager)xz.Deserialize(sr);
}
return manger;
}
透过反序列化的过程(Code001),我们应联想到类JobsManager应有xml-content-001中一此节点相关的属性。当然xml-content-001看起来更象一个数组或集合的一个序列化结果。以下Code002是初步的类
Code002
public class JobsManager
{
Job[] jobsSettings;
public Job[] JobsSettings
{
get { return jobsSettings; }
set { jobsSettings = value; }
}
}
public class Job
{
int interval;
public int Interval
{
get { return interval; }
set { interval = value; }
}
string workAt;
public string WorkAt
{
get { return workAt; }
set { workAt = value; }
}
string workBy;
public string WorkBy
{
get { return workBy; }
set { workBy = value; }
}
}
似乎我们也只能这样来定义的我们的类。当然,你如果现在就用上面的类来尝试执行Create方法,结果只能是异常。除非你在xml-content-001使用一个新的名为JobsManager来作为jobsSettings的父节点,并相应修改xml-content-002中的section name="jobsManager" 。数组节点项的名称也要微调一下。反序后,你会发现数组中每个Job项只有WorkBy被设置了正确的内容。
好,先不管Interval和WorkAt为什么没有内容。如果我执着的认为JobsManager和jobsSettings中的一层是多余的,一定要按xml-content-001来作为我配置节点的内容呢?XML序列化过程中通常会用数组名来作为各子项父节点,但可以使用XmlElementAttribute来去掉,在这里如果我想去掉jobsSettings这一层,可以这样来描述JobsManager的JobsSettings属性
Code003
Job[] jobsSettings;
[XmlElement("job")]
public Job[] JobsSettings
{
get { return jobsSettings; }
set { jobsSettings = value; }
}
如果我很固执,我认为JobsSettings比JobsManager更容易让人明白、意思更为贴切,能改变类序列化时的名称吗?XmlTypeAttribute可以。以下是对应xml-content-001完整的序列化-反序列化类
Code003
using System;
using System.Xml.Serialization;
[XmlType("jobsSettings")]
public class JobsManager
{
Job[] jobsSettings;
[XmlElement("job")]
public Job[] JobsSettings
{
get { return jobsSettings; }
set { jobsSettings = value; }
}
}
public class Job
{
int interval;
[XmlAttribute("interval")]
public int Interval
{
get { return interval; }
set { interval = value; }
}
string workAt;
[XmlAttribute("workAt")]
public string WorkAt
{
get { return workAt; }
set { workAt = value; }
}
string workBy;
public string WorkBy
{
get { return workBy; }
set { workBy = value; }
}
}