首页 > 代码库 > 自定义ConfigurationSection,创建多个嵌套的ConfigurationElementCollection节点

自定义ConfigurationSection,创建多个嵌套的ConfigurationElementCollection节点

本人现在在一家游戏公司,最近在做一个项目,需要做一个GM的管理后台,需要调用其他公司提供的接口,来实现后台管理的操作

由于接口地址都是固定的,所以想到使用自定义节点,来将接口都配置到web.config中。

很快,v1.0版本出炉: 

public class RequestConfigSection : ConfigurationSection    {        [ConfigurationProperty("sources", IsDefaultCollection = true)]        [ConfigurationCollection(typeof(RequestConfigSourceCollection), AddItemName = "add")]        public RequestConfigSourceCollection ConfigCollection        {            get { return (RequestConfigSourceCollection)this["sources"]; }            set { this["sources"] = value; }        }    }        public class RequestConfigSourceCollection : ConfigurationElementCollection    {        /// <summary>        /// 创建新元素        /// </summary>        /// <returns></returns>        protected override ConfigurationElement CreateNewElement()        {            return new RequestConfigSource();        }        /// <summary>        /// 获取元素的键        /// </summary>        /// <param name="element"></param>        /// <returns></returns>        protected override object GetElementKey(ConfigurationElement element)        {            return ((RequestConfigSource)element).Name;        }        /// <summary>        /// 获取所有键        /// </summary>        public IEnumerable<string> AllKeys { get { return BaseGetAllKeys().Cast<string>(); } }        /// <summary>        /// 索引器        /// </summary>        /// <param name="name"></param>        /// <returns></returns>        public new RequestConfigSource this[string name]        {            get { return (RequestConfigSource)BaseGet(name); }        }    }    public class RequestConfigSource : ConfigurationElement    {        /// <summary>        /// 名称        /// </summary>        [ConfigurationProperty("name")]        public string Name        {            get { return (string)this["name"]; }            set { this["name"] = value; }        }        /// <summary>        /// 地址        /// </summary>        [ConfigurationProperty("url")]        public string Url        {            get { return (string)this["url"]; }            set { this["url"] = value; }        }        /// <summary>        /// 访问类型        /// </summary>        [ConfigurationProperty("type")]        public RequestType RequestType        {            get            {                return (RequestType)Enum.Parse(typeof(RequestType), this["type"].ToString(), true);            }            set { this["type"] = value; }        }    }

 

在web.config中的配置方式为:

<apiRequestConfig>  <sources>    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />  </sources></apiRequestConfig>

 这时候又看了一遍需求文档,发现有说明不同平台的接口地址是不一样的,但接口做的事情是一样的。

然后就开始想,如果接着在下边追加,则不同平台的同一接口的名称是不能相同的。

所以想到的理想的配置方式为:

<apiRequestConfig>  <sources platform="android">    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />  </sources>  <sources platform="ios">    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />    <add name="..." url="..." type="POST" />  </sources></apiRequestConfig>

 但是sources 名称的节点只能出现一次…好吧,蛋疼了。

研究尝试了一上午也没有找到合适的解决方式,又懒得再重新写一套代码来读取XML,…开始在网上搜解决方案

用中文做关键字找不着…翻了墙,用英文来当关键字 one or more ConfigurationElementCollection…

最终在一老外的博客里找到了一个替代的解决方案,最终的配置为:

<apiRequestConfig>    <requestConfigs>      <request platform="android">        <sources>          <add name="..." url="..." type="POST" />          <add name="..." url="..." type="POST" />          <add name="..." url="..." type="POST" />        </sources>      </request>      <request platform="ios">        <sources>          <add name="..." url="..." type="POST" />          <add name="..." url="..." type="POST" />          <add name="..." url="..." type="POST" />        </sources>      </request>    </requestConfigs>  </apiRequestConfig>

 

C#代码如下:

public class RequestConfigSection : ConfigurationSection    {        [ConfigurationProperty("requestConfigs", IsDefaultCollection = true)]        [ConfigurationCollection(typeof(RequestConfigTypeCollection), AddItemName = "request")]        public RequestConfigTypeCollection ConfigCollection        {            get { return (RequestConfigTypeCollection)this["requestConfigs"]; }            set { this["requestConfigs"] = value; }        }        /// <summary>        /// 根据平台和名称获取请求配置信息        /// </summary>        /// <param name="name"></param>        /// <param name="platform"></param>        /// <returns></returns>        public RequestConfigSource GetRequestConfigSource(string platform, string name)        {            return ConfigCollection[platform].SourceCollection[name];        }    }    public class RequestConfigTypeCollection : ConfigurationElementCollection    {        /// <summary>        /// 创建新元素        /// </summary>        /// <returns></returns>        protected override ConfigurationElement CreateNewElement()        {            return new RequestConfigType();        }        /// <summary>        /// 获取元素的键        /// </summary>        /// <param name="element"></param>        /// <returns></returns>        protected override object GetElementKey(ConfigurationElement element)        {            return ((RequestConfigType)element).Platform;        }        /// <summary>        /// 获取所有键        /// </summary>        public IEnumerable<string> AllKeys { get { return BaseGetAllKeys().Cast<string>(); } }        /// <summary>        /// 索引器        /// </summary>        /// <param name="name"></param>        /// <returns></returns>        public new RequestConfigType this[string platform]        {            get { return (RequestConfigType)BaseGet(platform); }        }    }    public class RequestConfigType : ConfigurationElement    {        /// <summary>        /// 获取全部请求配置信息        /// </summary>        /// <returns></returns>        public RequestConfigSource[] GetAllRequestSource()        {            var keys = this.SourceCollection.AllKeys;            return keys.Select(name => this.SourceCollection[name]).ToArray();        }        /// <summary>        /// 平台标识        /// </summary>        [ConfigurationProperty("platform")]        public string Platform        {            get { return (string)this["platform"]; }            set { this["platform"] = value; }        }        [ConfigurationProperty("sources", IsDefaultCollection = true)]        [ConfigurationCollection(typeof(RequestConfigSourceCollection), AddItemName = "add")]        public RequestConfigSourceCollection SourceCollection        {            get { return (RequestConfigSourceCollection)this["sources"]; }            set { this["sources"] = value; }        }    }    public class RequestConfigSourceCollection : ConfigurationElementCollection    {        /// <summary>        /// 创建新元素        /// </summary>        /// <returns></returns>        protected override ConfigurationElement CreateNewElement()        {            return new RequestConfigSource();        }        /// <summary>        /// 获取元素的键        /// </summary>        /// <param name="element"></param>        /// <returns></returns>        protected override object GetElementKey(ConfigurationElement element)        {            return ((RequestConfigSource)element).Name;        }        /// <summary>        /// 获取所有键        /// </summary>        public IEnumerable<string> AllKeys { get { return BaseGetAllKeys().Cast<string>(); } }        /// <summary>        /// 索引器        /// </summary>        /// <param name="name"></param>        /// <returns></returns>        public new RequestConfigSource this[string name]        {            get { return (RequestConfigSource)BaseGet(name); }        }    }    /// <summary>    /// 请求的配置信息    /// </summary>    public class RequestConfigSource : ConfigurationElement    {        /// <summary>        /// 名称        /// </summary>        [ConfigurationProperty("name")]        public string Name        {            get { return (string)this["name"]; }            set { this["name"] = value; }        }        /// <summary>        /// 地址        /// </summary>        [ConfigurationProperty("url")]        public string Url        {            get { return (string)this["url"]; }            set { this["url"] = value; }        }        /// <summary>        /// 访问类型        /// </summary>        [ConfigurationProperty("type")]        public RequestType RequestType        {            get            {                return (RequestType)Enum.Parse(typeof(RequestType), this["type"].ToString(), true);            }            set { this["type"] = value; }        }    }

 

本人的开发环境为 .net framework 4.0

最初RequestConfigSection 类中的ConfigCollection 和  RequestConfigType 类中的SourceCollection  没有定义ConfigurationCollection特性

而是在RequestConfigTypeCollectionRequestConfigTypeCollection 中重载了ElementName属性,返回子级的节点名。

结果抛出节点名未定义的异常…

改由特性ConfigurationCollection定义,并给特性属性AddItemName赋值为子级的节点名 解决…

 

老外博客地址:http://tneustaedter.blogspot.com/2011/09/how-to-create-one-or-more-nested.html  需要FQ访问

或者直接看这儿,俺给Copy出来了:http://www.cnblogs.com/efenghuo/articles/4022836.html

自定义ConfigurationSection,创建多个嵌套的ConfigurationElementCollection节点