自定义配置节处理类

今天看别人的代码,发现原来是可以 自定义配置文件处理类 的。

 在此之前,先弄清两个概念:配置节配置元素

什么是配置节和配置元素?

下面给出一段XML:

 <system.webServer>
    <handlers>
      <add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=12.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode" />
    </handlers>

    <httpProtocol>
      <customHeaders>
        <add name="X-UA-Compatible" value="IE=EmulateIE7" />
      </customHeaders>
    </httpProtocol>

    <directoryBrowse enabled="true" />
  </system.webServer>

其中的<system.webServer></system.webServer>这样的成对出现、且可包含其他配置节或配置元素的,称之为配置节。

而配置元素:如其中的<directoryBrowse />这样以"/"结尾的配置项,称为配置元素。

而不管配置节或是配置元素都可以有属性,如:<directoryBrowse />中的enabled,属性是一个名值对。如:enabled="true"。

 

如何定义自定义配置节和配置元素

比如,我现在想定义如下的配置项:

<xhm.erp.remoting>
   <server host="127.0.0.1" port="8023" />
</xhm.erp.remoting>

如果只是在配置文件中定义了上面的配置节,是不起任何作用的,因为无法去读取其中的元素及其属性值。所以,需要自定义配置节处理类 。

下面就以上面提到的配置节的定义为例,进行讲解如何自定义配置节处理程序,使得可以从配置文件中正确解析如上配置节中的信息。

自定义配置节类(代码):

    /// <summary>
    /// 自定义配置节
    /// </summary>
    public class CustomSection:ConfigurationSection
    {
        private const string SECTION_NAME = "xhm.erp.remoting";//节名
        private const string ELEMENT_NAME = "server";//元素名

        /// <summary>
        /// 获得自定义配置节
        /// </summary>
        /// <returns></returns>
        internal static CustomSection getCustomSection()
        {
            return ConfigurationManager.GetSection(SECTION_NAME) as CustomSection;
        }

        /// <summary>
        /// Server元素 --- 未设为public,为什么?为了只让本程序集中的代码进行访问
        /// </summary>
        [ConfigurationProperty("server",IsRequired=true)]
        internal CustomElement ServerElement
        {
            get
            {
                return base[ELEMENT_NAME] as CustomElement;
            }

            set
            {
                base[ELEMENT_NAME] = value;
            }
        }
    }

    /// <summary>
    /// 自定义元素(包含两个属性: host和port)
    /// </summary>
    public class CustomElement : ConfigurationElement
    {
        private const string HOST = "host";//主机名
        private const string PORT = "port";//端口

        /// <summary>
        /// 主机
        /// </summary>
        [ConfigurationProperty("host",DefaultValue="127.0.0.1",IsRequired=true)]
        public string Host
        {
            get
            {
                return (string)base[HOST];
            }
            set
            {
                base[HOST] = value;
            }
        }

        /// <summary>
        /// 端口
        /// </summary>
        [ConfigurationProperty("port", DefaultValue = 12000)]
        [IntegerValidator(MinValue = 10000, MaxValue = 30000)]
        public int Port
        {
            get
            {
                return (int)base[PORT];
            }
            set
            {
                base[PORT] = value;
            }
        }
    }

上面就是针对xhm.erp.remoting节的结构定义的自定义配置文件节,有了它才可以通过ConfigurationManager.GetSection("xhm.erp.remoting")的方式获得该自定义配置节。因为GetSection方法返回的是一个object对象,需要还需要将其强转为CustomSection类型。

其实,如果在别的项目中引用该自定义配置节还是有一些问题的,因为ServerElement的访问修饰符定义为internal,这就意味着只有在本程序集中的代码才能访问该属性。

之所以在这里这样定义,是因为以后会在CustomSection类所在程序集中定义具体的ServerConfiguration和ClientCongfiguration类,以用于访问服务端和客户端的自定义配置节。这样就不需要直接获得ServerElement属性了。

 

定义了自定义配置节后,如何去用?

方法比较简单,直接在需要读配置文件的地方使用如下代码:

CustomSection cs = (CustomSection)ConfigurationManager.GetSection("xhm.erp.remoting");

 

但是在程序运行的过程中还是出现了一些问题:

1)首先,读取配置文件时,提示异常:配置系统未能初始化

InnerException: "无法识别的配置节 xhm.erp.remoting"

原因:

  未在配置文件中声明自定义配置节。

解决:

  在配置文件的configuration节的开头加入如下内容:

<configSections>
    <section name="xhm.erp.remoting" 
             type="Com.Xhm.RemotingConfiguration.CustomSection,RemotingConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
             allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" 
             restartOnExternalChanges="true" />
</configSections>

对自定义配置节进行声明,否则会报错。

一个用户自定义的配置节,在配置文件中分为两部分:

一是在<configSections></ configSections>配置节中声明配置节(上面配置文件模式中的“<section>”),

另外是在<configSections></ configSections >之后设置配置节(上面配置文件模式中的“<xhm.erp.remoting>”),有点类似一个变量先声明,后使用一样。

 所以完整的配置文件内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="xhm.erp.remoting"
             type="Com.Xhm.RemotingConfiguration.CustomSection,RemotingConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
             allowDefinition="Everywhere" allowExeDefinition="MachineToApplication"
             restartOnExternalChanges="true" />
  </configSections>
  
  <xhm.erp.remoting>
    <!--<server host="192.168.3.1" port="16890" />-->
    <!---不配置port,则默认端口为12000-->
    <server host="127.0.0.1" />
  </xhm.erp.remoting>
</configuration>

 

2)其次,又报了如下错误:提供的验证程序不支持属性“port”的类型。

原因:

        /// <summary>
        /// 端口
        /// </summary>
        [ConfigurationProperty("port",IsRequired=true),IntegerValidator(MinValue=10000,MaxValue=30000)]
        public string Port
        {
            get
            {
                return (string)base[PORT];
            }
            set
            {
                base[PORT]=value;
            }
        }

  属性定义代码中有不一致的地方,如这里的port定义为string类,但是在进行数据验证时,却是用整型的验证方法IntegerValidator。

解决:

  把port的类型该为int。

 

3)然后,又发现用ConfigurationManager.GetSection("xhm.erp.remoting");读取自定义配置节时,又提示:

   {"属性“port”的值无效。错误为: 该值必须在 10000-30000 范围内。"}

原因:

  IntegerValidator(MinValue=10000,MaxValue=30000)对数字进行限定时,好像必须在ConfigurationProperty中指定默认值。

解决:

  把CustomElement 中自定义属性的代码修改为:

        /// <summary>
        /// 端口
        /// </summary>
        //[ConfigurationProperty("port")]
        [ConfigurationProperty("port", DefaultValue = 12000)]
        [IntegerValidator(MinValue = 10000, MaxValue = 30000)]
        public int Port
        {
            get
            {
                return (int)base[PORT];
            }
            set
            {
                base[PORT] = value;
            }
        }

 

如果读取的server的host和port都是默认值,而不是在配置文件中配置的值。为什么?

 

posted on 2014-10-29 14:49  Leon-LYH  阅读(168)  评论(0)    收藏  举报

导航