这章内容大部分摘自 .NET之美 这本书的!
我们平常使用的appSettings及connectionStrings,在webconfig中并没有看到configSection节点 ,那是由哪个类型处理的呢?这是因为它们的节点处理类型定义在了machine.config中
<?xml version="1.0" encoding="UTF-8"?> <configuration> <configSections> <section name="appSettings" type="System.Configuration.AppSettingsSecti System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/> <section name="connectionStrings" type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"requirePermission="false"/> </configSections> </configuration>
可以看到,appSettings是由System.Configuration.AppSettingsSection类型处理的,connectionStrings则是由System.Configuration.ConnectionStringsSection类型处理的 ;
另外再观察一下machine.config就会发现,处理程序分成了两种类型:一种是以Section结尾的,比如AppSettingsSection和ConnectionStringsSection这两个;还有一种是
Handler结尾的,比如:
<section name="system.data.dataset" type="System.Configuration.NameValueFileSectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" restartOnExternalChanges="false"/>
可以看到type属性System.Configuration.NameValueFileSectionHandler是以Handler结尾的。 之所以会有这样的区别,是因为.NET中对于节点有两种处理方式,一种是定义一个继承自System.Configuration.ConfigurationSection的类,这也就是以Section结尾的类型;一种是实现System.Configuration.IConfigurationSectionHandler接口,也就是以Handler结尾的类型。 .NET Framework 2.0以后版本推荐采用继承ConfigurationSection类的方式。 本章的示例大多数采用的是IConfigurationSectionHandler接口的方式,同时也会提供一个继承
ConfigurationSection类的方式作为对比。
type由两部分组成,由逗号“,”分隔,前半部分是类型名称,后半部分是类型所在的程序集名称。
一、.NET内置处理程序
.NET内置的处理程序定义于machine.config中,提供全局服务,无须进行任何额外工作就可以直接使用。 但是使用内置节点在很多情况下不一定方便,比方说,我们
希望保存站点使用的邮件服务器的地址、 用户名和密码,那么以前的做法,配置文件会是类似这样的:
<appSettings> <add key="SiteName" value="TraceFact.Net"/> <add key="Version" value="v1.0.08040301" /> <add key="GreetingLanguage" value="Chinese" /> <add key="MailServer" value="mail.tracefact.net" /> <add key="MailUser" value="jimmyzhang" /> <add key="MailPassword" value="123456"/> </appSettings>
这样看起来比较散乱:MailServer、 MailUser、 MailPassword很明显是一组相关的数据,但是和其他的配置混在了一起。 如果可以自定义一个节点,情况就会好很多,比如:
<?xml version="1.0"?> <configuration> <!-- 其余略 --> <mailServeraddress="mail.tracefact.net" userName="jimmyzhang" password="123456 </configuration
这样看起来就好了很多,mailServer表示这是一个关于邮件服务器配置的节点,它的属性/值分别代表存储的相应值。
如果现在不做任何修改,直接运行程序,则会抛出异常“未经处理的异常:System.Configuration.ConfigurationErrorsException:配置系统未能初始化---
>System.Configuration.ConfigurationErrorsException:无法识别的配置节点mailServer。 ”。这是因为.NET底层的处理类型不认识这个节点。
为了避免发生这个错误,必须在configSection中指定对mailServer节点的处理程序 。有时候,我们希望绕过.NET的机制,直接使用System.Xml命名空间下的类来对配置文件(App.config
也是标准的Xml文件)进行操作,但是因为这里会报错,所以有的人干脆就新建一个xml文件,然后对新建的xml文件进行操作。 实际上,可以通过指定IgnoreSectionHandler或者
IgnoreSection处理程序的方式来进行处理,如同它们的名称所暗示的,这两个处理程序什么都不做,仅仅是让.NET忽略自定义的配置节点。 修改App.config,在根节点configuration下
创建configSections节点,然后再添加一个section节点,指定它的name属性值为mailServer,意为指定mailServer节点的处理程序,然后指定type为System.Configuration.IgnoreSection:
<?xml version="1.0"?> <configuration> <configSections> <!-- 使用IgnoreSection,可以将指定的XMl节点忽视掉 --> <section name="mailServer" type="System.Configuration.IgnoreSection,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" allowLocation="false" restartOnExternalChanges="true" /> </configSections> <!-- 自定义节点 mailServer --> <mailServer address="mail.tracefact.net" userName="jimmyzhang" password="123456 </configuration>
此时再次运行程序,就不会再抛出异常了 ;
二、 使用自定义节点和自定义处理程序
假如站点更大一些,只使用一个邮件服务器压力太大,需要设置多个邮件服务器,对于子域名forum.tracefact.net使用一个邮件服务器;对于blog.tracefact.net使用另一个邮件
服务器,这时应如何设置App.config呢? 此时,就会需要类似下面这样结构的配置:
<?xml version="1.0"?><configuration> <!--使用自定义节点和自定义处理程序 --> <mailServerGroup provider="www.edong.com"> <mailServer client="forum.tracefact.net"> <address>mail1.tracefact.net</address> <userName>jimmyzhang</userName> <password>123456</password> </mailServer> <mailServer client="blog.tracefact.com"> <address>mail2.tracefact.net</address> <userName>webmaster</userName> <password>456789</password> </mailServer> </mailServerGroup> </configuration>
mailServerGroup节点包含了所有关于邮件服务器的信息。 它的provider属性说明邮件服务器是由哪个ISP(Internet Service Provider互联网服务供应商)提供的,这里是中国易动
网(www.edong.com)。 其下的节点mailServer是指具体的邮件服务器,client说明此邮件服务器为哪个域名提供服务,address说明邮件服务器的地址,userName和password分别为
用户名和密码。
处理方式有两种,一种是实现IConfigurationSectionHandler接口,一种是继承ConfigurationSection类。
1.0 自定义节点处理程序—实现IConfigurationSectionHandler接口
IConfigurationSectionHandler接口的定义如下 :
// // 摘要: // 处理对特定的配置节的访问。 public interface IConfigurationSectionHandler { // // 摘要: // 创建配置节处理程序。 // // 参数: // parent: // 父对象。 // // configContext: // 配置上下文对象。 // // section: // 节 XML 节点。 // // 返回结果: // 创建的节处理程序对象。 object Create(object parent, object configContext, XmlNode section); }
它只要求实现一个方法:Create(),当在ConfigurationManager对象上调用GetSection("sectionName")方法的时候,实际上会委托给这个Create()方法进行处理。 这个
方法最重要的一个参数是类型为XmlNode的section,它代表着名为"sectionName"的节点。它返回一个object类型的对象,这个对象通常是自定义的一个关于这个节点的配置对象,对
象的字段和属性映射节点的属性和文本值,用以提供强类型的访问(也可以返回一个Hashtable,这样就无须自定义类型)。
节点在传递时有一个类型转换,在调用GetSection()时,传递的是String类型的节点名称;而在Create()方法中,传递的是该名称的XmlNode类型的节点。
//未完,有空再写