您的位置:首页 > 其它

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

2016-10-26 15:43 477 查看
由于接口地址都是固定的,所以想到使用自定义节点,来将接口都配置到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 类中的ConfigCollectionRequestConfigType 类中的SourceCollection 没有定义ConfigurationCollection特性

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

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

改由特性ConfigurationCollection定义,并给特性属性AddItemName赋值为子级的节点名 解决…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: