appSettings太简单,为每个程序自定义配置节点太复杂,因此要解决app.config&web.config自定义配置的复用问题。

1.读取不依赖SectionName,根节点可以定义为任何名称。

2.足够简单,配置项采用name value的形式;足够复杂,采用树型结构,每个节点都可以有多个配置项和子节点。

3.使用简单,采用路径简化配置项的读取。如: config.Get<string>("root.sub.item-test")。

一、调用方式:

1.配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="node" type="Onion.Configuration.AppConfig.ConfigSection,Onion.Configuration" /></configSections><node name="root"><items><item name="version" value="1.0.0.1" /></items><nodes><node name="runtime"><items><item name="debug" value="false" /><item name="ioc" value="IoC.Contianer.StructureMapIoC" /></items></node><node name="upload"><items><item name="auth" value="true" /><item name="path" value="~/upload" /><item name="url" value="~/Upload/Index" /></items></node><node name="captcha"><items><item name="timeout" value="3000" /><item name="url" value="~/Captcha/Index" /></items></node><node name="oauth2"><items><item name="disabled" value ="false" /><item name="callback" value ="/Home/ExternalLoginCallBack?ProviderName=" /></items><nodes><node name="qqclient"><items><item name="disabled" value="false" /><item name="method" value="get" /><item name="key" value="9233e24d" /><item name="secret" value="1ac35907-7cfa-4079-975c-959b98d23a95" /></items></node><node name="weiboclient"><items><item name="disabled" value="true" /><item name="method" value="post" /><item name="key" value="0cdea8f3" /><item name="secret" value="dc679dbb-7e75-44f7-a99e-5359259fc94b" /></items></node></nodes></node></nodes></node>
</configuration>

2.调用代码:

[Fact]public void Tests(){var config = new AppConfigAdapter();Assert.True(config.Get<string>("version") == "1.0.0.1");Assert.True(config.Get<bool>("runtime.debug") == false);Assert.True(config.Get<string>("runtime.ioc") == "IoC.Contianer.StructureMapIoC");Assert.True(config.Get<bool>("upload.auth") == true);Assert.True(config.Get<string>("upload.path") == "~/upload");Assert.True(config.Get<string>("upload.url") == "~/Upload/Index");Assert.True(config.Get<int>("captcha.timeout") == 3000);Assert.True(config.Get<string>("captcha.url") == "~/Captcha/Index");Assert.True(config.Get<bool>("oauth2.disabled") == false);Assert.True(config.Get<string>("oauth2.callback") == "/Home/ExternalLoginCallBack?ProviderName=");Assert.True(config.GetNode("oauth2").Nodes.Any(o => o.GetItem<bool>("disabled")));foreach (var node in config.GetNode("oauth2").Nodes){if (node.Name == "qqclient"){Assert.True(node.GetItem<bool>("disabled") == false);Assert.True(node.GetItem<string>("method") == "get");Assert.True(node.GetItem<string>("key") == "9233e24d");Assert.True(node.GetItem<string>("secret") == "1ac35907-7cfa-4079-975c-959b98d23a95");}else if (node.Name == "weiboclient"){Assert.True(node.GetItem<bool>("disabled") == true);Assert.True(node.GetItem<string>("method") == "post");Assert.True(node.GetItem<string>("key") == "0cdea8f3");Assert.True(node.GetItem<string>("secret") == "dc679dbb-7e75-44f7-a99e-5359259fc94b");}}}

二、接口定义:

1.配置项定义:IItem接口定义最基础的配置项,只包含Name和Value属性。

public interface IItem
{string Name { get; set; }string Value { get; set; }
}

2.配置节点定义:INode接口定义了配置节点的树形结构

public interface INode
{string Name { get; set; }IEnumerable<IItem> Items { get; set; }IEnumerable<INode> Nodes { get; set; }string GetItem(string itemName);T GetItem<T>(string itemName);
}

3.读取接口定义:IConfig接口定义了配置节点和配置项的读取

public interface IConfig
{INode GetNode(string nodeName);string Get(string nameOrPath);T Get<T>(string nameOrPath);
}

以上3个接口定义了所有的逻辑。

三、接口实现:

1.自定义ItemElement(IItem)和ItemElementCollection用于实现单个节点的配置项读取。

    public class ItemElement : ConfigurationElement, IItem{[ConfigurationProperty("name", IsRequired = true)]public string Name{get { return Convert.ToString(this["name"]); }set { this["name"] = value; }}[ConfigurationProperty("value", IsRequired = true)]public string Value{get { return Convert.ToString(this["value"]); }set { this["value"] = value; }}}public class ItemElementCollection : ConfigurationElementCollection, IEnumerable<IItem>{protected override ConfigurationElement CreateNewElement(){return new ItemElement();}protected override object GetElementKey(ConfigurationElement element){return ((ItemElement)element).Name;}public new IEnumerator<IItem> GetEnumerator(){for (int i = 0; i < base.Count; i++){yield return base.BaseGet(i) as IItem;}}}

View Code

2.自定义NodeElement(INode)和NodeElementCollection用于实现节点树功能。

    public class NodeElement : ConfigurationElement, INode{[ConfigurationProperty("name", IsRequired = true)]public string Name{get { return Convert.ToString(this["name"]); }set { this["name"] = value; }}[ConfigurationProperty("items")][ConfigurationCollection(typeof(ItemElementCollection), AddItemName = "item")]public ItemElementCollection ItemElements{get{return this["items"] as ItemElementCollection;}set { this["items"] = value; }}[ConfigurationProperty("nodes")][ConfigurationCollection(typeof(NodeElementCollection), AddItemName = "node")]public NodeElementCollection NodeElements{get{return this["nodes"] as NodeElementCollection;}set { this["nodes"] = value; }}public IEnumerable<IItem> Items{get{return this["items"] as ItemElementCollection;}set { this["items"] = value; }}public IEnumerable<INode> Nodes{get{return this["nodes"] as NodeElementCollection;}set { this["nodes"] = value; }}public string GetItem(string itemName){return this.Items.FirstOrDefault(o => o.Name == itemName)?.Value;}public T GetItem<T>(string itemName){return (T)Convert.ChangeType(this.GetItem(itemName), typeof(T));}}public class NodeElementCollection : ConfigurationElementCollection, IEnumerable<INode>{protected override ConfigurationElement CreateNewElement(){return new NodeElement();}protected override object GetElementKey(ConfigurationElement element){return ((NodeElement)element).Name;}public new IEnumerator<INode> GetEnumerator(){for (int i = 0; i < base.Count; i++){yield return base.BaseGet(i) as INode;}}}

View Code

3.自定义ConfigSection实现配置节点和配置项读取。

    public class ConfigSection : ConfigurationSection, INode{[ConfigurationProperty("name", IsRequired = true)]public string Name{get { return Convert.ToString(this["name"]); }set { this["name"] = value; }}[ConfigurationProperty("items")][ConfigurationCollection(typeof(ItemElementCollection), AddItemName = "item")]public ItemElementCollection ItemElements{get{return this["items"] as ItemElementCollection;}set { this["items"] = value; }}[ConfigurationProperty("nodes")][ConfigurationCollection(typeof(NodeElementCollection), AddItemName = "node")]public NodeElementCollection NodeElements{get{return (NodeElementCollection)this["nodes"];}set { this["nodes"] = value; }}public IEnumerable<IItem> Items{get{return this["items"] as ItemElementCollection;}set { this["items"] = value; }}public IEnumerable<INode> Nodes{get{return (NodeElementCollection)this["nodes"];}set { this["nodes"] = value; }}public string GetItem(string itemName){return this.Items.FirstOrDefault(o => o.Name == itemName)?.Value;}public T GetItem<T>(string itemName){return (T)Convert.ChangeType(this.GetItem(itemName), typeof(T));}}

View Code

4.自定义AppConfigAdapter实现IConfig接口。

    public class AppConfigAdapter : IConfig{private INode _section;public AppConfigAdapter(){var sectionName = (HostingEnvironment.IsHosted ? WebConfigurationManager.OpenWebConfiguration("~") : ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)).Sections.Cast<ConfigurationSection>().FirstOrDefault(o => o.SectionInformation.Type.IndexOf("Onion.Configuration.AppConfig.ConfigSection") != -1).SectionInformation.Name ?? "Node";_section = (INode)ConfigurationManager.GetSection(sectionName);}public INode GetNode(string nodeName){return this.GetNode(nodeName, this._section);}public string Get(string nameOrPath){if (nameOrPath.IndexOf('.') == -1){return this._section.Items.FirstOrDefault(o => o.Name == nameOrPath)?.Value;}var nodeItemPath = nameOrPath.Split('.');var node = this.GetNode(nodeItemPath.FirstOrDefault());var nodeNameList = nodeItemPath.Skip(1).Take(nodeItemPath.Length - 2);if (node != null){foreach (var item in nodeNameList){if (node.Nodes.Any(o => o.Name == item)){node = node.Nodes.FirstOrDefault(o => o.Name == item);}else{throw new System.ArgumentException(string.Format("node name {0} error", item));}}return node.Items.FirstOrDefault(o => o.Name == nodeItemPath.LastOrDefault()).Value;}return null;}public T Get<T>(string nameOrPath){var value = this.Get(nameOrPath);return (T)Convert.ChangeType(value, typeof(T));}#region privateprivate INode GetNode(string nodeName, INode node){INode result = null;if (node.Name == nodeName){return node;}else if (node.Nodes.Any()){foreach (var item in node.Nodes){result = GetNode(nodeName, item);if (result != null){break;}}}return result;}#endregion private}

View Code

Nuget:https://www.nuget.org/packages/Onion.Configuration/

转载于:https://www.cnblogs.com/easygame/p/5051592.html

ASP.NET系列:自定义配置节点的复用相关推荐

  1. app.config自定义配置节点

    本来一直用xml保存配置文件的,但有一个组件就写一个好麻烦.于是想起了自定义配置节点哈哈~~我撒娇了复习了下 首先我在ConfigManager.Instance使用单例模式,其次Reflection ...

  2. springboot跳转html_畅游Spring Boot系列 — 自定义配置

    这里要说的自定义配置主要是两类:一类是关于Spring MVC的扩展配置,一类是Spring Boot自身通过配置文件的自定义配置 首先,我们来看一下SpringBoot中关于Spring MVC的相 ...

  3. Asp.Net web.config配置节点大全详解

    web.config 文件查找规则: (1)如果在当前页面所在目录下存在web.config文件,查看是否存在所要查找的结 点名称,如果存在返回结果并停止查找. (2)如果当前页面所在目录下不存在we ...

  4. 在asp.net2.0中使用串行化对象实现自定义配置

    在一次升级一个entlib1.0到entlib的高版本程序时,碰到entlib的一个通过XmlSerializer方式实现的自定义配置.而在entlib的高版本中这样的配置不再被支持.可是又不希望修改 ...

  5. ASP.NET Core 配置 - 创建自定义配置提供程序

    ASP.NET Core 配置 - 创建自定义配置提供程序 在本文中,我们将创建一个自定义配置提供程序,从数据库读取我们的配置.我们已经了解了默认配置提供程序的工作方式,现在我们将实现我们自己的自定义 ...

  6. SpringSecurity权限管理框架系列(六)-Spring Security框架自定义配置类详解(二)之authorizeRequests配置详解

    1.预置演示环境 这个演示环境继续沿用 SpringSecurit权限管理框架系列(五)-Spring Security框架自定义配置类详解(一)之formLogin配置详解的环境. 2.自定义配置类 ...

  7. Asp.net Web.Config - 配置元素customErrors

    Asp.net配置文件的配置方式,其实在MSDN里面是写得最清楚的了.可惜之前一直未曾了解到MSDN的强大. 先贴个地址:http://msdn.microsoft.com/zh-cn/library ...

  8. ASP.NET Core的配置(2):配置模型详解

    在上面一章我们以实例演示的方式介绍了几种读取配置的几种方式,其中涉及到三个重要的对象,它们分别是承载结构化配置信息的Configuration,提供原始配置源数据的ConfigurationProvi ...

  9. .Net Core 自定义配置源从配置中心读取配置

    配置,几乎所有的应用程序都离不开它..Net Framework时代我们使用App.config.Web.config,到了.Net Core的时代我们使用appsettings.json,这些我们再 ...

最新文章

  1. CentOS 7 相关命令
  2. TCP实现服务器与单客户端连接(多线程)
  3. 城科会刘朝晖:从互联网大脑模型看城市大脑
  4. jsp用session判断输入框_[实战小剧场servletamp;jsp] 用户登录及退出功能实现
  5. 《PHP精粹:编写高效PHP代码》——2.1节数据持久化和Web应用程序
  6. 【bzoj3224】 Tyvj1728—普通平衡树
  7. 【随机过程】随机过程之泊松过程的推广
  8. .Net WinForm 启用XP效果的问题
  9. Hadoop(七)Hive基础
  10. 随想录(多学一点汇编语言)
  11. 模拟计算器进行四则运算(同等优先级)(内测第2届第3题)
  12. Echarts数据可视化legend图例,开发全解+完美注释
  13. 外接键盘Win键不能的使用问题以及FN键的使用
  14. WIZnet 物联网设计大赛 - WizFi360大赛
  15. php 调用reboot,Linux命令:reboot命令
  16. MySQLdb 安装小结
  17. 阿里 java 面试题 p6_「独家」五面阿里P6:Java开发面试题及答案
  18. 宜家IKEA EDIFACT PRODAT报文详解
  19. C语言 习题3-1 比较大小 (简单解法)
  20. 【Minecraft】10分钟教你搭建我的世界Java版开服教程【Linux服务器+MCSManager管理面板】

热门文章

  1. JavaScript URL参数读取
  2. SQL DISTINCT 多字段查询用法
  3. 使用svn进行版本控制
  4. Spring学习笔记(三)
  5. Linux基础命令---su 1
  6. 关于iOS里的做动画方法的差别与注意事项
  7. .NET Core TDD 前传: 编写易于测试的代码 -- 全局状态
  8. 看我如何基于PythonFacepp打造智能监控系统
  9. 【图片服务器】搭建Nginx图片服务器
  10. ASP.NET学习笔记