Dottext中的配置
开发asp.net应用的时候,我们一般都把系统的环境配置信息放在web.config中,如果参数很少,一般就直接放在<appSettings>配置节中即可。但对于一些较大型的应用,有很多参数需要设置,仅依赖于<appSettings>的平面结构就不够了,需要一种能提供多层配置信息的结构。
Dottext中的配置就是这样一种多层的结构,它非常巧妙的使用了.Net中的Xml序列化,使得配置结构非常简单却又很强大。
要向web.config中加入自己的配置节,必须开发相应的配置节处理程序,Dottext使用了一个公共的配置节处理程序:
public class XmlSerializerSectionHandler : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, System.Xml.XmlNode section)
{
XPathNavigator nav = section.CreateNavigator();
string typename = (string) nav.Evaluate("string(@type)");
Type t = Type.GetType(typename);
XmlSerializer ser = new XmlSerializer(t);
return ser.Deserialize(new XmlNodeReader(section));
}
}
在web.config中的BlogConfigurationSettings配置节定义如下:
<BlogConfigurationSettings type = "Dottext.Framework.Configuration.BlogConfigurationSettings, Dottext.Framework">
在代码中,一般是这样来使用配置设置:
Config.Settings.BlogProviders.DTOProvider
而Settings在Config中是这样定义的:
public static BlogConfigurationSettings Settings
{
get
{
return ((BlogConfigurationSettings)ConfigurationSettings.GetConfig("BlogConfigurationSettings"));
}
}
当用GetConfig获取ConfigurationSettings配置信息的时候,它会调用该配置节的处理程序XmlSerializerSectionHandler的Create方法,以返回正确的配置设置。在其Create方法中,通过访问配置节的type属性来得到具体类型,然后通过XmlSerializer将web.config中的以xml格式配置的设置信息反序列化为具体的BlogConfigurationSettings对象。
这中间的关键就是要定义好提供配置信息的类——BlogConfigurationSettings,这样我们才能使用类似Config.Settings.UseXHTML的方式获取在web.config中定义的参数,而不是使用Convert.ToBoolean(AppSettings["Blog.UseXHTML"])。
一般情况下,一个类只要加上Serializable特性进行声明就可以作为这样的配置类了:
[Serializable]
public class BlogConfigurationSettings
但仍然要注意几点:interface和abstract class不能作为配置类;类必须要有不带参数的公共构造函数;要作为配置参数的字段或者属性必须是public的,而属性必须有set。
默认情况下,Xml序列化会把类中的字段或者属性序列化成xml Element,比如上面的UseXHTML,但有些时候,可能要使用xml Attribute,比如:
<Tracking enableAggBugs = "true" …
这种情况,需要使用XmlAttributeAttribute来声明:
[XmlAttribute("enableAggBugs")]
public bool EnableAggBugs
多数情况下,我们定义的配置类应该已经足够,但偶尔有些时候,我们需要在配置文件中增加配置元素或者配置属性,但又不能或者不想修改已有的配置类,为了避免反序列化的时候出错,也为了增强灵活性,应该给配置类增加这样两个属性:
[XmlAnyAttribute]
public XmlAttribute[] XmlAttributes
[XmlAnyElement]
public XmlElement[] XmlElements
这是告诉XmlSerializer,如果有不可识别的元素或者属性,则将其放到这样两个数组中,程序可以从数组中检索相应的设置。
Dottext中还定义了这样的结构:
<EntryHandlers>
<EntryHandler type="..." postType = "Comment" processAction ="Insert" processState="PreCommit" isAsync="false" />
...
</EntryHandlers>
[XmlArray("EntryHandlers")]
public EntryHandler[] EntryHandlers
这样就可以定义数组参数。如果数组的元素不是同样的类型,但都继承自一个基类,那还可以这样定义:
<Validators>
<RegularExpressionValidator Name="Email" ...
<DateValidator Name="Date" ...
...
</Validators>
[XmlArray("Validators")]
[
XmlArrayItem("Validator", typeof(Nss.Data.Validators.Validator))
,
XmlArrayItem("RegularExpressionValidator", typeof(Nss.Data.Validators.RegularExpressionValidator))
]
public Nss.Data.Validators.Validator[] Validators;
XmlArray定义了数组,而XmlArrayItem定义了数组中可以使用的元素类型,使得系统的配置更加灵活,结构也更清晰。
以前总是为配置发愁,要写那么多代码,自从发现了Dottext的配置后,真是由衷的佩服,于是拿来就用,在自己的项目中也使用了这样的配置结构,期间也遇到了不少问题,所幸最后都解决了,于是就写了这篇小文,希望能够抛砖引玉,让更多的人来发掘Dottext中的宝藏。