代码改变世界

程序自定义配置节 小结

2012-07-26 16:52  谢中涞  阅读(1066)  评论(1编辑  收藏  举报

随着程序功能的越来越复杂,所需要配置也越来越多,看着程序配置文件中<appSettings>节点里面的<add key="" value="">已经需要拖动好几次滚动条才能看完的时候,让人感觉确实有点....,"自定义配置"这个东东已出现好多年了,早已不是什么新鲜事了,今天在此小结一下吧,给一听到配置就弄一堆形如<add key="" value="">的兄弟们,说一下,配置其实还有这种实现, 今天不讨论这种自定义配置节和默认的<add key="" value="">孰优孰劣,这个就留给大家自己去斟酌吧, 至于为什么要使用自定义配置节,我想这个就不用赘述了.

  1. 假定我们按照功能分类,我们希望我们的自定义配置节大致为如下样子.

image

2. 在上图中,可以看出我们的配置文件大概由4部分组成.

  • 配置节根的中的属性 "DefaultUrl"
  • Shop节点,其中包括了"ShopId","MerchantId”以及”MD5Key” 属性.
  • UrlNodes 节点,看这个结构,应该为一个列表来着.
  • Timer 节点,其中包括了 "Up", "Down”, "UpAndDown", ”CheckUpdate” 属性

3. 有了上面的分析,我们大致画个UML类图来形象展示一下

image

4.有的兄弟可能会说了,此篇文章不是讲自定义配置节的吗, 怎么又画起了类结构图了? 这是因为要实现自定义配置节的解析,我们确确实实的需要定义一个和配置节类似的一个类来承载解析的数据. 在正式构建之前,我们需要先大致了解一下下面的规则.

  • 既然是一个自定义的配置节,那么这个类肯定需要继承于System.Configuration.ConfigurationSection

  • 自定义配置节中的每个节点,我们称之为元素,需要继承于System.Configuration.ConfigurationElement

  • 如果是集合类元素(如此处的UrlNodes节点),需要继承于System.Configuration.ConfigurationElementCollection

  • 元素的属性,我们通过System.Configuration.ConfigurationPropertyAttribute 特性标识.

5.有了上面的一系列准备,下面我们就按照上面的类图来构建我们的自定义配置节解析类.

  • Shop元素:
 
    /// <summary>
    /// 店铺配置节
    /// </summary>
    internal class ShopElement : ConfigurationElement
    {
        /// <summary>
        /// 店铺Id
        /// </summary>
        [ConfigurationProperty("ShopId", IsRequired = true)]
        public string ShopId
        {
            get
            {
                return (string)base["ShopId"];
            }
            set
            {
                base["ShopId"] = value;
            }
        }

        /// <summary>
        /// 商家Id
        /// </summary>
        [ConfigurationProperty("MerchantId", IsRequired = true)]
        public string MerchantId
        {
            get
            {
                return (string)base["MerchantId"];
            }
            set
            {
                base["MerchantId"] = value;
            }
        }

        /// <summary>
        /// 加密key
        /// </summary>
        [ConfigurationProperty("MD5Key", IsRequired = true)]
        public string MD5Key
        {
            get
            {
                return (string)base["MD5Key"];
            }
            set
            {
                base["MD5Key"] = value;
            }
        }
    }
  • UrlNodes 元素
 
/// <summary>
    /// 同步节点
    /// </summary>
    internal class UrlNodeElement : ConfigurationElement
    {
        /// <summary>
        /// 节点名称
        /// </summary>
        [ConfigurationProperty("Name", IsRequired = true, IsKey = true)]
        public string Name
        {
            get
            {
                return (string)base["Name"];
            }
            set
            {
                base["Name"] = value;
            }
        }

        /// <summary>
        /// 服务端Url
        /// </summary>
        [ConfigurationProperty("Url", IsRequired = true)]
        public string Url
        {
            get
            {
                return (string)base["Url"];
            }
            set
            {
                base["Name"] = value;
            }
        }
    }

    /// <summary>
    /// 同步节点集合
    /// </summary>
    internal class UrlNodes : ConfigurationElementCollection
    {
        /// <summary>
        /// 创建一个新节点
        /// </summary>
        /// <returns>新的 System.Configuration.ConfigurationElement</returns>
        protected override ConfigurationElement CreateNewElement()
        {
            return new UrlNodeElement();
        }

        /// <summary>
        /// 获取指定配置元素的元素键。
        /// </summary>
        /// <param name="element">要为其返回键的 System.Configuration.ConfigurationElement</param>
        /// <returns>一个 System.Object,用作指定 System.Configuration.ConfigurationElement 的键</returns>
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((UrlNodeElement)element).Name;
        }

        /// <summary>
        /// 根据序列顺序 获取第 index个元素
        /// </summary>
        /// <param name="index">元素顺序序列</param>
        /// <returns>SyncNodeSection</returns>
        public UrlNodeElement this[int index]
        {
            get
            {
                return (UrlNodeElement)base.BaseGet(index);
            }
        }

        /// <summary>
        /// 根据元素名称 获取名称为key的元素
        /// </summary>
        /// <param name="key">元素名称</param>
        /// <returns>SyncNodeSection</returns>
        public new UrlNodeElement this[string key]
        {
            get
            {
                return (UrlNodeElement)base.BaseGet(key);
            }
        }
    }
  • Timer 元素, 从结构上可以得知这个元素基本上和 Shop元素类似,在此不再赘述.
  • 根节点,
 
 /// <summary>
    /// 封装读取客户端配置节
    /// </summary>
    internal class ClientSyncSection : ConfigurationSection
    {
        /// <summary>
        /// 店铺节点
        /// </summary>
        [ConfigurationProperty("Shop", IsDefaultCollection = true)]
        public ShopElement Shop
        {
            get
            {
                return (ShopElement)base["Shop"];
            }
            set
            {
                base["Shop"] = value;
            }
        }

        /// <summary>
        /// 同步节点集合
        /// </summary>
        [ConfigurationProperty("UrlNodes", IsDefaultCollection = false)]
        [ConfigurationCollection(typeof(UrlNodeElement), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
        public UrlNodes UrlNodes
        {
            get
            {
                return (UrlNodes)base["UrlNodes"];
            }
            set
            {
                base["UrlNodes"] = value;
            }
        }

        /// <summary>
        /// 数据同步定时间隔
        /// </summary>
        [ConfigurationProperty("Timer", IsDefaultCollection = true)]
        public TimerElement Timer
        {
            get
            {
                return (TimerElement)base["Timer"];
            }
            set
            {
                base["Timer"] = value;
            }
        }

        /// <summary>
        /// 默认接口网址
        /// </summary>
        [ConfigurationProperty("DefaultUrl", IsDefaultCollection = true)]
        public string DefaultUrl
        {
            get
            {
                return (string)base["DefaultUrl"];
            }
            set
            {
                base["DefaultUrl"] = value;
            }
        }
    }

6. 注册配置节,在configSections 节点中 增加解析配置的程序集与对应的类名. image

7. 使用, 我们可以通过下面的示例代码,来访问我们设定的配置. image

另外,自定义配置节还可以设置配置节组<sectionGroup>,这个可以参见http://msdn.microsoft.com/zh-cn/library/ms228114(v=vs.80).aspx,在此就不再赘述了. 至此,我们本篇的自定义配置节的使用就介绍到这里了,希望可以帮助到有类似需求的同学们.