.Net 自定义应用程序配置(参照张子阳博客)

     在开发的时候我们有时需要对应用程序做某些特殊的配置。我们希望保存站点使用的邮件服务器的地址、用户名和密码,那么按照AppSetting的做法,我想应该是这样的

<add key="MailServer" value="mail.tracefact.net" />
<add key="MailUser" value="jimmyzhang" />
<add key="MailPassword" value="123456"/>

      这样的话配置及使用并不方便:首先,很明显这三个add是一组数据,但是除了凭自己的经验判断,再没有任何办法进行区分;其次,如果我们有多组服务器或者很多配置,我们需要写很长的add结点。如果我们可以自定一个结点,情况就会好很多,比如我们在Web.Config中添加一个结点:

<?xml version="1.0"?>
<configuration>
<!-- 其余略 -->
<mailServer address="mail.tracefact.net" userName="jimmyzhang" password="123456" />
</configuration>

      这样看起来就好了很多,mailServer表示这是一个关于邮件服务器配置的结点,它的属性/值 分别代表存储的相应的值。以后我们在程序中进行发送邮件时可以根据这里的值来对发送邮件的对象进行参数设置。本节我们就来看下如何在web.Config中使用我们自定义的结点,但使用.Net内置的处理程序。

注意:在web.config中,结点以及属性的命名遵循Camel命名方式,也就是首字母小写,其后的每个单词首字母大些的方式。

      接着在站点中添加一个 Simple.aspx 文件,打开它。此时编译器会报错,提示:“分析器错误信息: 无法识别的配置节 mailServer”。 .Net已经提供了很多内置的处理程序,为了避免发生这个错误,我们必须在configSection中指定对mailServer结点的处理程序。有时候我们希望绕过.Net的机制,直接使用System.Xml命名空间下的类来对配置文件(web.config也是标准的Xml文件)进行操作,但是因为这里会报错,所以有的人干脆就另建一个xml文件了事,然后对新建的xml文件进行操作。

      实际上,可以通过指定IgnoreSectionHandler 或者 IgnoreSection 处理程序的方式来进行处理,如同它们的名称所暗示的,这两个处理程序什么都不做,仅仅是让.Net 忽略我们的自定义结点。修改 web.Config ,在根节点configuration下创建configSections结点,然后再添加一个section结点,指定它的name属性值为mailServer,意为指定mailServer结点的处理程序,然后指定type为System.Configuration.IgnoreSection。

      在.Net中,还有一个较为常用的处理程序,就是System.Configuration.SingleTagSectionHandler,它会以Hashtable的形式返回结点的所有属性。当我们使用System.Configuration.SingleTagSectionHandler时,调用GetSection()方法会返回一个Hashtable(当调用GetSection()方法时,会潜在地执行configSection中相应结点所指定的type类型的方法),Hashtable的key为属性的名称,Hashtable的value为属性的值。

     上面的使用方式存在着两个问题:     

     1.采用Hashtable的方法,由于key是字符串类型,除非你将结点的属性全部背过了,不然我们不得不去查看web.config文件,找到属性,然后才能书写代码去获取(比如 mailServer["address"])。而不能使用Vs提供的自动提示功能,也就是强类型访问的能力,这样的话使用起来很不方便。

     2.假如我们的站点大了一些,只使用一个邮件服务器可能压力太大,我们需要设置多个邮件服务器,对于子域名 forum.tracefact.net 使用一个邮件服务器;对于 blog.tracefact.net使用另一个邮件服务器,这时我们要如何设置Web.Config呢?

       

此时,我们可能会需要下面这样结构的配置:

代码
<?xml version="1.0"?>
<configuration>
<!-- SimpleCustom.aspx, 使用自定义结点和自定义处理程序 -->
<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类。我们先看如何通过实现接口IConfigurationSectionHandler去实现。

      自定义结点处理程序 – 实现IConfigurationSectionHandler接口

      IConfigurationSectionHandler 接口的定义如下:

      它只要求实现一个方法:Create(),当我们在ConfigurationManager对象上调用GetSection("sectionName")方法的时候,实际上会委托给这个Create()方法进行处理。这个方法最重要的一个参数是类型为XmlNode的section,它代表着名为“sectionName”的结点。它返回一个object类型的对象,这个对象通常是我们自定义的一个关于这个结点的配置对象,对象的字段和属性映射结点的属性和文本值,来提供强类型的访问(你也可以返回一个Hashtable,这样就无需自定义类型)。

namespace System.Configuration {
public interface IConfigurationSectionHandler {
object Create(object parent, object configContext, XmlNode section);
}
}

 

 

       注意结点在在传递时有一个转换,调用GetSection()时,传递的是String类型的结点名称;而在Create()方法中,传递的是该名称的XmlNode类型的结点。

posted @ 2010-12-30 13:39  雁北飞  阅读(216)  评论(0编辑  收藏  举报