zoukankan      html  css  js  c++  java
  • 扩展配置节

    这章内容大部分摘自  .NET之美 这本书的!

     <!--所有节点属性 configSource 可以将扩展文件放入外部-->

    我们平常使用的appSettingsconnectionStrings,在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结尾的,比如AppSettingsSectionConnectionStringsSection这两个;还有一种是

    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>

    这样看起来比较散乱:MailServerMailUserMailPassword很明显是一组相关的数据,但是和其他的配置混在了一起。 如果可以自定义一个节点,情况就会好很多,比如:

    <?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节点的处理程序,然后指定typeSystem.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属性说明邮件服务器是由哪个ISPInternet Service Provider互联网服务供应商)提供的,这里是中国易动
    网(www.edong.com)。 其下的节点mailServer是指具体的邮件服务器,client说明此邮件服务器为哪个域名提供服务,address说明邮件服务器的地址,userNamepassword分别为
    用户名和密码。

    处理方式有两种,一种是实现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()方法进行处理。 这个
    方法最重要的一个参数是类型为XmlNodesection,它代表着名为"sectionName"的节点。它返回一个object类型的对象,这个对象通常是自定义的一个关于这个节点的配置对象,对
    象的字段和属性映射节点的属性和文本值,用以提供强类型的访问(也可以返回一个Hashtable,这样就无须自定义类型)。

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

    示例:

    <!--配置-->
     <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>
    

    读取方法:

        /// <summary>
        /// mailServerGroup 下面的各个MailServer节点
        /// </summary>
        public class MailServer
        {
            // 存储mailServer的子节点(Address,UserName,Password)的innerText值
            // 以及属性 Client 的值
            private Hashtable serverNode;
            public MailServer()
            {
                serverNode = new Hashtable();
            }
    
            public Hashtable ServerNode
            {
                get { return serverNode; }
            }
            public string Client
            {
                get { return serverNode["client"] as string; }
            }
            public string Address
            {
                get { return serverNode["address"] as string;}
            }
            public string UserName
            {
                get {return serverNode["userName"] as string;}
            }
            public string Password
            {
                get{ return serverNode["password"] as string;}
            }
        }
      /// <summary>
        ///这个类用于映射mailServerGroup整体节点。 对mailServerGroup节点的属性以及子节点的访问,均通过这个类来进行
        /// </summary>
        public class MailServerConfig : List<MailServer>
        {     
          public string Provider { get; set; }
    
        
        }
    
       public class MailServerConfigurationHandler : IConfigurationSectionHandler
        {
            /// <summary>
            /// // section 为 MailServerGroup 节点,即根节点的位置
            /// </summary>
            /// <param name="parent"></param>
            /// <param name="configContext"></param>
            /// <param name="section"></param>
            /// <returns></returns>
            public object Create(object parent, object configContext, XmlNode section)
            {
                // 设置方法返回配置对象,可以是任何类型
                MailServerConfig config = new MailServerConfig();
             
                config.Provider = section.Attributes["provider"] == null ? "" : section.Attributes["provider"].Value;
              
                foreach (XmlNode child in section.ChildNodes)
                {
                    MailServer server = new MailServer();
                    if (child.Attributes["client"] != null)
                    {
                        server.ServerNode.Add("client", child.Attributes["client"].Value);
                    }
                    // 获取MailServer下的 Name,UserName,Password 节点
                    foreach (XmlNode grandChild in child.ChildNodes)
                    {
                        // 添加文本
                        server.ServerNode.Add(grandChild.Name, grandChild.InnerText);
                    } 
                    // 将server加入MailServerConfig
                    config.Add(server);
                }
                return config;
            }
        }
    

    使用:

         MailServerConfig serverGroup = (MailServerConfig)ConfigurationManager.GetSection("mailServerGroup");
                Console.WriteLine("使用自定义节点和自定义处理程序");
                Console.WriteLine("Provider:".PadRight(12, ' ') + serverGroup.Provider);
                foreach (MailServer config in serverGroup)
                {
                    Console.WriteLine("--------------------------------------------");
                    Console.WriteLine("Client:".PadRight(12, ' ') + config.Client);
                    Console.WriteLine("Address:".PadRight(12, ' ') + config.Address);
                    Console.WriteLine("User Name:".PadRight(12, ' ') + config.UserName);
                    Console.WriteLine("PassWord:".PadRight(12, ' ') + config.Password);
                }
    
                Console.ReadKey();
    

    2.自定义节点处理程序继承ConfigurationSection基类 ;示例如下:

     <mailServerGroup2  provider="www.edong.com" >
        <mailServers>
          <mailServer
          client="forum.tracefact.net"
          address="mail1.tracefact.net"
          userName="jimmyzhang"
          password="123456" />
          <mailServer
          client="blog.tracefact.net"
          address="mail2.tracefact.net"
          userName="webmaster"
          password="456789" />
        </mailServers>
      </mailServerGroup2>
    /// <summary>
        /// MailServer 节点; 这里面的对应我们配置文件节点的属性
        /// </summary>
        public class MailServerElement : ConfigurationElement
        {
          
            [ConfigurationProperty("client", IsKey = true, IsRequired = true)]
            public string Client
            {
                get { return this["client"] as string; }
                set { this["client"] = value; }
            }
            [ConfigurationProperty("address")]
            public string Address
            {
                get { return this["address"] as string; }
                set { this["address"] = value; }
            }
            [ConfigurationProperty("userName")]
            public string UserName
            {
                get { return this["userName"] as string; }
                set { this["userName"] = value; }
            }
            [ConfigurationProperty("password")]
            public string Password
            {
                get { return this["password"] as string; }
                set { this["password"] = value; }
            }
    
        } /// <summary>    ///MailServer 集合类;一般情况下重写CreateNewElement,GetElementKey方法和用索引获取即可
    /// </summary>
      [ConfigurationCollection(typeof(MailServer), AddItemName = "mailServer")]
    public class MailServerCollection : ConfigurationElementCollection { public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } protected override ConfigurationElement CreateNewElement() { return new MailServerElement(); } /// <summary> /// 获取元素的key /// </summary> /// <param name="element"></param> /// <returns></returns> protected override object GetElementKey(ConfigurationElement element) { return ((MailServerElement)element).Client; } protected override string ElementName { get { return "mailServer"; } } public new int Count { get { return base.Count; } } public MailServerElement this[int index] { get { return (MailServerElement)BaseGet(index); } set { if (BaseGet(index) != null) { BaseRemoveAt(index); } BaseAdd(index, value); } } new public MailServerElement this[string Name] { get { return (MailServerElement)BaseGet(Name); } } public int IndexOf(MailServerElement element) { return BaseIndexOf(element); } public void Add(MailServerElement element) { BaseAdd(element); } public void Remove(MailServerElement element) { if (BaseIndexOf(element) >= 0) BaseRemove(element.Client); } public void RemoveAt(int index) { BaseRemoveAt(index); } public void Remove(string client) { BaseRemove(client); } public void Clear() { BaseClear(); } }
      public class MailServerSection:System.Configuration.ConfigurationSection
        {
            [ConfigurationProperty("provider", IsKey = true)]
            public string Provider { get { return this["provider"] as string; } }
            [ConfigurationProperty("mailServers", IsDefaultCollection = false)]
            public MailServerCollection MailServers
            {
                get
                {
                    return (MailServerCollection)this["mailServers"];
                }
                set
                {
                    this["mailServers"] = value;
                }
            }
    
        }

    使用:

        MailServerSection mailSection = (MailServerSection)ConfigurationManager.GetSection("mailServerGroup2");
                Console.WriteLine("使用自定义节点和自定义处理程序");
                Debugger.Break();
                Console.WriteLine("Provider:".PadRight(12, ' ') + mailSection.Provider);
                foreach (MailServerElement config in mailSection.MailServers)
                {
                    Console.WriteLine("--------------------------------------------");
                    Console.WriteLine("Client:".PadRight(12, ' ') + config.Client);
                    Console.WriteLine("Address:".PadRight(12, ' ') + config.Address);
                    Console.WriteLine("User Name:".PadRight(12, ' ') + config.UserName);
                    Console.WriteLine("PassWord:".PadRight(12, ' ') + config.Password);
                }
    
                Console.ReadKey();
  • 相关阅读:
    Linux curl命令详解
    drools 7 日期时间段校验
    java程序员常用查询和学习的网站
    springboot+mybatis+分页插件的使用
    Vue. 之 替换 左上角 title标签处的图标
    Github访问速度很慢的原因,以及解决方法
    vue插件总结——总有你能用上的插件
    在Java中如何高效的判断数组中是否包含某个元素
    解决vue刷新页面以后丢失store的数据
    vue路由跳转时组件data数据刷新
  • 原文地址:https://www.cnblogs.com/entclark/p/8687610.html
Copyright © 2011-2022 走看看