一步一步教你玩转.NET Framework的配置文件app.config
转自https://www.cnblogs.com/tonnie/archive/2010/12/17/appconfig.html
<configuration>
<appSettings>
<add key="MyConfigString" value="Test Config Data"/>
</appSettings>
</configuration>
public class AppSettingConfig
{
public string resultValue;
public AppSettingConfig()
{
this.resultValue = ConfigurationManager.AppSettings["MyConfigString"].ToString();
}
}
[TestMethod]
public void TestAppSettingConfigNode()
{
AppSettingConfig appCon = new AppSettingConfig();
Assert.AreEqual("Test Config Data", appCon.resultValue);
}
没有问题!
我们加个Section来看看如何访问:
<configuration>
<configSections>
<sectionGroup name="MySectionGroup">
<section name="MyFirstSection" type="System.Configuration.DictionarySectionHandler"/>
<section name="MySecondSection" type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup> </configSections>
<MySectionGroup>
<MyFirstSection>
<add key="First" value="First Section"/>
</MyFirstSection>
<MySecondSection>
<add key="Second" value="Second Section"/>
</MySecondSection>
</MySectionGroup>
</configuration>
注意我们在section的type中给出了System.Configuration.DictionarySectionHandler,这也限制了我们在具体的ConfigurationElement中只能使用<add key=”” value=””/>的形式,使得我们GetSection()方法返回的是一个IDictory对象,我们可以根据Key来取得相应的值
public class SectionConfig
{
public string resultValue;
public SectionConfig()
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); IDictionary dic = ConfigurationManager.GetSection("MySectionGroup/MySecondSection") as IDictionary;
this.resultValue = dic["Second"].ToString(); }
}
[TestMethod]
public void TestSectionGroupConfigNode()
{
SectionConfig sc = new SectionConfig();
Assert.AreEqual("First Section", sc.resultValue);
}
还是没问题。
2. 中级玩法
.NET支持对上述提到的configuration类进行扩展,我们可以定义自己的Section。
继承自基类System.Configuration.ConfigurationSection,ConfigurationSection已经提供了索引器用来获取设置数据。
在类中加上ConfigurationProperty属性来定义Section中的Element:
public class CustomSection:System.Configuration.ConfigurationSection
{
[ConfigurationProperty("sectionId", IsRequired=true, IsKey=true)]
public int SectionId {
get { return (int)base["sectionId"]; }
set { base["sectionId"] = value; }
} [ConfigurationProperty("sectionValue", IsRequired = false)]
public string SectionValue {
get { return base["sectionValue"].ToString(); }
set { base["sectionValue"] = value; }
}
}
操作此Section,我们将其动态加入app.config中,并读出来:
public class CustomSectionBroker
{
private CustomSection customSection = null;
public void InsertCustomSection()
{
customSection = new CustomSection();
customSection.SectionId = 1;
customSection.SectionValue = "The First Value";
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("CustomSection", customSection);
config.Save(ConfigurationSaveMode.Minimal);
} public int GetCustomSectionID()
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
CustomSection cs = config.GetSection("CustomSection") as CustomSection;
return cs.SectionId;
}
} [TestMethod]
public void TestCustomSection()
{
CustomSectionBroker cb = new CustomSectionBroker();
cb.InsertCustomSection();
Assert.AreEqual(1, cb.GetCustomSectionID());
}
可以看下现在app.config文件的变化:
<configuration>
<configSections>
<section name="CustomSection" type="Tonnie.Configuration.Library.CustomSection, Tonnie.Configuration.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<sectionGroup name="MySectionGroup">
<section name="MyFirstSection" type="System.Configuration.DictionarySectionHandler"/>
<section name="MySecondSection" type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup> </configSections>
<CustomSection sectionId="1" sectionValue="The First Value" />
<MySectionGroup>
<MyFirstSection>
<add key="First" value="First Section"/>
</MyFirstSection>
<MySecondSection>
<add key="Second" value="Second Section"/>
</MySecondSection>
</MySectionGroup>
</configuration>
public abstract class CustomSectionElementBase:System.Configuration.ConfigurationElement
{
[ConfigurationProperty("childId", IsRequired=true, IsKey=true)]
public int ChildID
{
get{return (int)base["childId"];}
set{base["childId"] = value;}
} [ConfigurationProperty("childValue", IsRequired=true)]
public string ChildValue
{
get{return base["childValue"].ToString();}
set{base["childValue"] = value;}
}
} public class CustomSectionElementA:CustomSectionElementBase
{
public CustomSectionElementA()
{
base.ChildID = 1;
base.ChildValue = "ChildA";
}
}
public class CustomSectionElementB:CustomSectionElementBase
{
public CustomSectionElementB()
{
base.ChildID = 2;
base.ChildValue = "ChildB";
}
}
public class CustomSectionWithChildElement:System.Configuration.ConfigurationSection
{
private const string elementChildA = "childSectionA";
private const string elementChildB = "childSectionB"; [ConfigurationProperty(elementChildA, IsRequired=true, IsKey=true)]
public CustomSectionElementA ChildSectionA {
get { return base[elementChildA] as CustomSectionElementA; }
set { base[elementChildA] = value; }
} [ConfigurationProperty(elementChildB, IsRequired = true)]
public CustomSectionElementB ChildSectionB {
get { return base[elementChildB] as CustomSectionElementB; }
set { base[elementChildB] = value; }
}
} public class CustomSectionWithChildElementBroker
{
private CustomSectionWithChildElement customSection = null;
public void InsertCustomSection()
{
customSection = new CustomSectionWithChildElement();
customSection.ChildSectionA = new CustomSectionElementA();
customSection.ChildSectionB= new CustomSectionElementB(); System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("CustomSectionWithChildElement", customSection);
config.Save(ConfigurationSaveMode.Minimal);
} public int GetCustomSectionChildAID()
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
CustomSectionWithChildElement cswe = config.GetSection("CustomSectionWithChildElement") as CustomSectionWithChildElement;
return cswe.ChildSectionA.ChildID;
}
}
红色字体就是修改的地方了,将Property改成我们自定义类的形式.测试代码如下:
[TestMethod]
public void TestCustomSectionWithChildElement()
{
CustomSectionWithChildElementBroker cweb = new CustomSectionWithChildElementBroker();
cweb.InsertCustomSection();
Assert.AreEqual(1, cweb.GetCustomSectionChildAID());
}
看看运行后我们的app.config变成什么样子了:
<configuration>
<configSections>
<section name="CustomSectionWithChildElement" type="Tonnie.Configuration.Library.CustomSectionWithChildElement, Tonnie.Configuration.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<section name="CustomSection" type="Tonnie.Configuration.Library.CustomSection, Tonnie.Configuration.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<sectionGroup name="MySectionGroup">
<section name="MyFirstSection" type="System.Configuration.DictionarySectionHandler"/>
<section name="MySecondSection" type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup> </configSections>
<CustomSectionWithChildElement>
<childSectionA childId="1" childValue="ChildA" />
<childSectionB childId="2" childValue="ChildB" />
</CustomSectionWithChildElement>
<CustomSection sectionId="1" sectionValue="The First Value" />
<MySectionGroup>
<MyFirstSection>
<add key="First" value="First Section"/>
</MyFirstSection>
<MySecondSection>
<add key="Second" value="Second Section"/>
</MySecondSection>
</MySectionGroup>
</configuration>
cool,好像完成了我们的要求。
下面为我们的CustomSectionWithChildElement外面再加一层SectionGroup.
public class CustomSectionGroup : System.Configuration.ConfigurationSectionGroup
{
[ConfigurationProperty("customSectionA", IsRequired = true, IsKey = true)]
public CustomSectionWithChildElement SectionA
{
get { return base.Sections["customSectionA"] as CustomSectionWithChildElement; }
set
{
this.Sections.Add("customSectionA", value);
}
}
}
public class CustomSectionGroupWithChildElementBroker
{
private CustomSectionWithChildElement customSection = null;
public void InsertCustomSectionGroup()
{
customSection = new CustomSectionWithChildElement();
customSection.ChildSectionA = new CustomSectionElementA();
customSection.ChildSectionB= new CustomSectionElementB(); CustomSectionGroup sectionGroup = new CustomSectionGroup();
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.GetSectionGroup("customSectionGroup") == null)
config.SectionGroups.Add("customSectionGroup",sectionGroup);
sectionGroup.SectionA = customSection;
config.Save(ConfigurationSaveMode.Minimal);
} public int GetCustomSectionChildAID()
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); CustomSectionWithChildElement cswe = config.GetSection("customSectionGroup/customSectionA") as CustomSectionWithChildElement;
return cswe.ChildSectionA.ChildID;
}
}
测试一下:
[TestMethod]
public void TestCustomSectionGroupWithChildElement()
{
CustomSectionGroupWithChildElementBroker cweb = new CustomSectionGroupWithChildElementBroker();
cweb.InsertCustomSectionGroup();
Assert.AreEqual(1, cweb.GetCustomSectionChildAID());
}
没问题,看下现在的app.config,是不是更加结构化了:
<configuration>
<configSections>
<sectionGroup name="MySectionGroup">
<section name="MyFirstSection" type="System.Configuration.DictionarySectionHandler"/>
<section name="MySecondSection" type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup> <sectionGroup name="customSectionGroup" type="Tonnie.Configuration.Library.CustomSectionGroup, Tonnie.Configuration.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" >
<section name="customSectionA" type="Tonnie.Configuration.Library.CustomSectionWithChildElement, Tonnie.Configuration.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</sectionGroup>
</configSections>
<MySectionGroup>
<MyFirstSection>
<add key="First" value="First Section"/>
</MyFirstSection>
<MySecondSection>
<add key="Second" value="Second Section"/>
</MySecondSection>
</MySectionGroup>
<customSectionGroup>
<customSectionA>
<childSectionA childId="1" childValue="ChildA" />
<childSectionB childId="2" childValue="ChildB" />
</customSectionA>
</customSectionGroup>
</configuration>
3 高级玩法
到目前为止可能大家对app.config有了一定的认识了,我们自己可以不断的去扩展.NET Framework提供给我们的类,从SectionGroup,Section,ElementCollection,Element 从上自下的一级一级的组装成符合工程化项目配置文件需要的形式。当遇到可能配置元素的类型属性差不多时,可以抽象出一个base类来。比如可以抽象出Section这一层面的base类,或者ElementCollection,Element这一层的抽象类(可以是抽象的泛型类)来。同时增加泛型来更好的支持扩展。具体例子下次再给了。
附上所有代码:/Files/tonnie/Tonnie.Configuration.rar
一点点心得,欢迎交流……
一步一步教你玩转.NET Framework的配置文件app.config的更多相关文章
- 一步一步教你如何在linux下配置apache+tomcat(转)
一步一步教你如何在linux下配置apache+tomcat 一.安装前准备. 1. 所有组件都安装到/usr/local/e789目录下 2. 解压缩命令:tar —vxzf 文件名(. ...
- 一步一步教你将普通的wifi路由器变为智能广告路由器
一步一步教你将普通的wifi路由器变为智能广告路由器 相信大家对WiFi智能广告路由器已经不再陌生了,现在很多公共WiFi上网,都需要登录并且验证,这也就是WiFi广告路由器的最重要的功能.大致就是下 ...
- 一步一步教你使用Git
一步一步教你使用Git 互联网给我们带来方便的同时,也时常让我们感到困惑.随便搜搜就出一大堆结果,然而总是有大量的重复和错误.小妖发出的内容,都是自己实测过的,有问题请留言. 现在,你已经安装了Git ...
- 使用WPF教你一步一步实现连连看
使用WPF教你一步一步实现连连看(一) 第一步: 问题,怎样动态的建立一个10*10的grid(布局) for (int i = 0; i < 10; i++){ RowDefinition r ...
- 一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app
一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app 转载 作者:jrainlau 链接:https://segmentfault.com/a/1190000005844155 ...
- Ace教你一步一步做Android新闻客户端(一)
复制粘贴了那么多博文很不好意思没点自己原创的也说不出去,现在写一篇一步一步教你做安卓新闻客户端,借此机会也是让自己把相关的技术再复习一遍,大神莫笑,专门做给新手看. 手里存了两篇,一个包括软件视图 和 ...
- 一步一步教你实现iOS音频频谱动画(二)
如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第一篇:一步一步教你实现iOS音频频谱动画(一) 本文是系列文章中的第二篇,上篇讲述了音频播放和频谱数据计算,本篇讲 ...
- 一步一步教你实现iOS音频频谱动画(一)
如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第二篇:一步一步教你实现iOS音频频谱动画(二) 基于篇幅考虑,本次教程分为两篇文章,本篇文章主要讲述音频播放和频谱 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布
之前的章节我们介绍了如何通过dapr发起一个服务调用,相信看过前几章的小伙伴已经对dapr有一个基本的了解了,今天我们来聊一聊dapr的另外一个功能--订阅发布 目录:一.通过Dapr实现一个简单的基 ...
随机推荐
- java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
转自:https://blog.csdn.net/rchm8519/article/details/23788053 1. ERROR - Context initialization failedo ...
- JavaScript高级程序设计学习笔记第六章--面向对象程序设计
1.ECMAScript没有类的概念,ECMA-262 把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.”,有点类似于散列表 2.ECMAScript 中有两种属性:数据属性和访问 ...
- Connection reset by peer的常见原因及解决办法
转自:https://blog.csdn.net/xc_zhou/article/details/80950753 1,如果一端的Socket被关闭(或主动关闭,或因为异常退出而 引起的关闭),另一端 ...
- Fluuter常遇到的问题
The ADB binary found at XX is obsolete and has seriousperformance problems with the Android Emulator ...
- SharePoint 2010 将带有工作流的模板移动到另一个站点集
HOWTO Move or Migrate SharePoint 2010 List-based Workflows between Sites and Site Collections I’ve e ...
- appium服务——封装生成可用端口
一.判断端口是否可用 1.在windows中判断端口是否可用,使用dos命令"netstat -ano| findstr 8080".运行结果有如下两种 如果没有被占用,就是结果为 ...
- 今天是 Java 诞生日,Java 24 岁了!
今天是 Java 诞生日,Java 今年 24 岁了,比栈长还年轻..还有得搞,别慌!作为一名Java语言的学习者,对Java的起源和发展有个大概的了解应是必要的. 1991年,Sun公司成立Gree ...
- UML工具 PlantUML SequenceDiagram
- Maven项目编译版本的问题和Spring中没有导入核心包
idea中maven项目的编译: 方案1:maven的settings.xml中指定全局默认编译版本 <profile> <id>jdk-1.8</id> < ...
- Django (十三) 项目部署 3
阿里云项目部署 部署Django项目 1, 配置nginx 1.1 进入:cd /var/www, 将外面压缩好的AXF项目拖入xshell中,并解压 1.2 配置nginx.conf: 将htt ...