使用.NET Framework的配置文件app.config
2016-06-16 10:13
429 查看
在一般的项目中,为了使你的代码更加灵活,更方便调整,减少不必要的hardcode,我们都在config中添加许多配置信息,一般可以选择.NET自带的配置文件形式app.config或者web项目中的web.config来完成配置工作。
.NET中提供了几个和配置有关的类来支持用完轻松的完成配置文件的读写设置:
System.Configuration.ConfigurationSectionGroup
一般和你项目中使用的Assambly保持1:1的对应关系,这样划分使得结构相对清晰,权责明确。当然你可以不使用它,这样一旦你的Assambly在别的地方要被重用时,找出相应的config信息就变得很困难。
System.Configuration.ConfigurationSection
维护一个相对独立的配置节,使用时需现在<ConfigSections></ConfigSections>节点下声明。我们熟悉的<appSettings></appSettings>以及<connectionStrings></connectionStrings/>就是.NET为我们预留的一个Section。
System.Configuration.ConfigurationElementCollection&[b]System.Configuration.ConfigurationElement[/b]
就是Section下具体的配置信息和配置信息的集合了。
下面来看看怎么使用这些类玩转app.config
1.初级使用
最初级的用法当然是使用<appSettings/>,我们在app.config中添加
访问它
增加了一个单独的Section,名为"CustomSection",并且包含了我们创建的2个configurationProperty。
我们还可以继续作扩展,现在我们的config中section的部分呈现的是<CustomSectionsectionId="1"sectionValue="TheFirstValue"/>,这样对于复杂的配置信息仍然不方便,我们是不是可以继续扩展,将其变成比较合理的
<CustomSection>
<ChildCustomSectionAchildId=1childValue=”ChildA”></ChildCustomSectionA>
<ChildCustomSectionBchildid=2childValue=”ChildB”></ChildCustomSectionB>
</CustomSection>
这种方式呢?我们为<ChildCustomSectionA></ChildCustomSectionA>创建扩展自ConfigurationElement类的子类CustomSectionElementA,然后修改CustomSection类中的Property,使得类型不再是int或string,而是我们创建的新类CustomSectionElementA.
由于ChildCustomSectionA和ChildCustomSectionB的结构相对一致,根据面向对象的开发封闭原则,我们可以先抽象出一个base类,然后让ChildCustomSectionA,ChildCustomSectionB分别继承自此base类,当以后要添加更多的ChildCustomSectionC,ChildCustomSectionD…时,使用这种Template的设计模式,将更加灵活。
完成了ConfigurationElement的实现,我们可以改写我们上一个例子中定义的CustomSection类了:
看看运行后我们的app.config变成什么样子了:
cool,好像完成了我们的要求。
下面为我们的CustomSectionWithChildElement外面再加一层SectionGroup.
.NET中提供了几个和配置有关的类来支持用完轻松的完成配置文件的读写设置:
System.Configuration.ConfigurationSectionGroup
一般和你项目中使用的Assambly保持1:1的对应关系,这样划分使得结构相对清晰,权责明确。当然你可以不使用它,这样一旦你的Assambly在别的地方要被重用时,找出相应的config信息就变得很困难。
System.Configuration.ConfigurationSection
维护一个相对独立的配置节,使用时需现在<ConfigSections></ConfigSections>节点下声明。我们熟悉的<appSettings></appSettings>以及<connectionStrings></connectionStrings/>就是.NET为我们预留的一个Section。
System.Configuration.ConfigurationElementCollection&[b]System.Configuration.ConfigurationElement[/b]
就是Section下具体的配置信息和配置信息的集合了。
下面来看看怎么使用这些类玩转app.config
1.初级使用
最初级的用法当然是使用<appSettings/>,我们在app.config中添加
<configuration> <appSettings> <addkey="MyConfigString"value="TestConfigData"/> </appSettings> </configuration>
访问它
publicclassAppSettingConfig { publicstringresultValue; publicAppSettingConfig() { this.resultValue=ConfigurationManager.AppSettings["MyConfigString"].ToString(); } } [TestMethod] publicvoidTestAppSettingConfigNode() { AppSettingConfigappCon=newAppSettingConfig(); Assert.AreEqual("TestConfigData",appCon.resultValue); }
没有问题!
我们加个Section来看看如何访问:
<configuration>
<configSections>
<sectionGroupname="MySectionGroup">
<sectionname="MyFirstSection"type="System.Configuration.DictionarySectionHandler"/>
<sectionname="MySecondSection"type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup>
</configSections>
<MySectionGroup>
<MyFirstSection>
<addkey="First"value="FirstSection"/>
</MyFirstSection>
<MySecondSection>
<addkey="Second"value="SecondSection"/>
</MySecondSection>
</MySectionGroup>
</configuration>
注意我们在section的type中给出了System.Configuration.DictionarySectionHandler,这也限制了我们在具体的ConfigurationElement中只能使用<addkey=””value=””/>的形式,使得我们GetSection()方法返回的是一个IDictory对象,我们可以根据Key来取得相应的值
publicclassSectionConfig
{
publicstringresultValue;
publicSectionConfig()
{
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
IDictionarydic=ConfigurationManager.GetSection("MySectionGroup/MySecondSection")asIDictionary;
this.resultValue=dic["Second"].ToString();
}
}
[TestMethod]
publicvoidTestSectionGroupConfigNode()
{
SectionConfigsc=newSectionConfig();
Assert.AreEqual("FirstSection",sc.resultValue);
}
还是没问题。
2.中级使用
.NET支持对上述提到的configuration类进行扩展,我们可以定义自己的Section。
继承自基类System.Configuration.ConfigurationSection,ConfigurationSection已经提供了索引器用来获取设置数据。
在类中加上ConfigurationProperty属性来定义Section中的Element:
publicclassCustomSection:System.Configuration.ConfigurationSection
{
[ConfigurationProperty("sectionId",IsRequired=true,IsKey=true)]
publicintSectionId{
get{return(int)base["sectionId"];}
set{base["sectionId"]=value;}
}
[ConfigurationProperty("sectionValue",IsRequired=false)]
publicstringSectionValue{
get{returnbase["sectionValue"].ToString();}
set{base["sectionValue"]=value;}
}
}
操作此Section,我们将其动态加入app.config中,并读出来:
publicclassCustomSectionBroker
{
privateCustomSectioncustomSection=null;
publicvoidInsertCustomSection()
{
customSection=newCustomSection();
customSection.SectionId=1;
customSection.SectionValue="TheFirstValue";
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("CustomSection",customSection);
config.Save(ConfigurationSaveMode.Minimal);
}
publicintGetCustomSectionID()
{
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
CustomSectioncs=config.GetSection("CustomSection")asCustomSection;
returncs.SectionId;
}
}
[TestMethod]
publicvoidTestCustomSection()
{
CustomSectionBrokercb=newCustomSectionBroker();
cb.InsertCustomSection();
Assert.AreEqual(1,cb.GetCustomSectionID());
}
可以看下现在app.config文件的变化:
<configuration>
<configSections>
<sectionname="CustomSection"type="Tonnie.Configuration.Library.CustomSection,Tonnie.Configuration.Library,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
<sectionGroupname="MySectionGroup">
<sectionname="MyFirstSection"type="System.Configuration.DictionarySectionHandler"/>
<sectionname="MySecondSection"type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup>
</configSections>
<CustomSectionsectionId="1"sectionValue="TheFirstValue"/>
<MySectionGroup>
<MyFirstSection>
<addkey="First"value="FirstSection"/>
</MyFirstSection>
<MySecondSection>
<addkey="Second"value="SecondSection"/>
</MySecondSection>
</MySectionGroup>
</configuration>
增加了一个单独的Section,名为"CustomSection",并且包含了我们创建的2个configurationProperty。
我们还可以继续作扩展,现在我们的config中section的部分呈现的是<CustomSectionsectionId="1"sectionValue="TheFirstValue"/>,这样对于复杂的配置信息仍然不方便,我们是不是可以继续扩展,将其变成比较合理的
<CustomSection>
<ChildCustomSectionAchildId=1childValue=”ChildA”></ChildCustomSectionA>
<ChildCustomSectionBchildid=2childValue=”ChildB”></ChildCustomSectionB>
</CustomSection>
这种方式呢?我们为<ChildCustomSectionA></ChildCustomSectionA>创建扩展自ConfigurationElement类的子类CustomSectionElementA,然后修改CustomSection类中的Property,使得类型不再是int或string,而是我们创建的新类CustomSectionElementA.
由于ChildCustomSectionA和ChildCustomSectionB的结构相对一致,根据面向对象的开发封闭原则,我们可以先抽象出一个base类,然后让ChildCustomSectionA,ChildCustomSectionB分别继承自此base类,当以后要添加更多的ChildCustomSectionC,ChildCustomSectionD…时,使用这种Template的设计模式,将更加灵活。
publicabstractclassCustomSectionElementBase:System.Configuration.ConfigurationElement
{
[ConfigurationProperty("childId",IsRequired=true,IsKey=true)]
publicintChildID
{
get{return(int)base["childId"];}
set{base["childId"]=value;}
}
[ConfigurationProperty("childValue",IsRequired=true)]
publicstringChildValue
{
get{returnbase["childValue"].ToString();}
set{base["childValue"]=value;}
}
}
publicclassCustomSectionElementA:CustomSectionElementBase
{
publicCustomSectionElementA()
{
base.ChildID=1;
base.ChildValue="ChildA";
}
}
publicclassCustomSectionElementB:CustomSectionElementBase
{
publicCustomSectionElementB()
{
base.ChildID=2;
base.ChildValue="ChildB";
}
}
完成了ConfigurationElement的实现,我们可以改写我们上一个例子中定义的CustomSection类了:
publicclassCustomSectionWithChildElement:System.Configuration.ConfigurationSection
{
privateconststringelementChildA="childSectionA";
privateconststringelementChildB="childSectionB";
[ConfigurationProperty(elementChildA,IsRequired=true,IsKey=true)]
publicCustomSectionElementAChildSectionA{
get{returnbase[elementChildA]asCustomSectionElementA;}
set{base[elementChildA]=value;}
}
[ConfigurationProperty(elementChildB,IsRequired=true)]
publicCustomSectionElementBChildSectionB{
get{returnbase[elementChildB]asCustomSectionElementB;}
set{base[elementChildB]=value;}
}
}
publicclassCustomSectionWithChildElementBroker
{
privateCustomSectionWithChildElementcustomSection=null;
publicvoidInsertCustomSection()
{
customSection=newCustomSectionWithChildElement();
customSection.ChildSectionA=newCustomSectionElementA();
customSection.ChildSectionB=newCustomSectionElementB();
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("CustomSectionWithChildElement",customSection);
config.Save(ConfigurationSaveMode.Minimal);
}
publicintGetCustomSectionChildAID()
{
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
CustomSectionWithChildElementcswe=config.GetSection("CustomSectionWithChildElement")asCustomSectionWithChildElement;
returncswe.ChildSectionA.ChildID;
}
}
红色字体就是修改的地方了,将Property改成我们自定义类的形式.测试代码如下:
[TestMethod]
publicvoidTestCustomSectionWithChildElement()
{
CustomSectionWithChildElementBrokercweb=newCustomSectionWithChildElementBroker();
cweb.InsertCustomSection();
Assert.AreEqual(1,cweb.GetCustomSectionChildAID());
}
看看运行后我们的app.config变成什么样子了:
<configuration>
<configSections>
<sectionname="CustomSectionWithChildElement"type="Tonnie.Configuration.Library.CustomSectionWithChildElement,Tonnie.Configuration.Library,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
<sectionname="CustomSection"type="Tonnie.Configuration.Library.CustomSection,Tonnie.Configuration.Library,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
<sectionGroupname="MySectionGroup">
<sectionname="MyFirstSection"type="System.Configuration.DictionarySectionHandler"/>
<sectionname="MySecondSection"type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup>
</configSections>
<CustomSectionWithChildElement>
<childSectionAchildId="1"childValue="ChildA"/>
<childSectionBchildId="2"childValue="ChildB"/>
</CustomSectionWithChildElement>
<CustomSectionsectionId="1"sectionValue="TheFirstValue"/>
<MySectionGroup>
<MyFirstSection>
<addkey="First"value="FirstSection"/>
</MyFirstSection>
<MySecondSection>
<addkey="Second"value="SecondSection"/>
</MySecondSection>
</MySectionGroup>
</configuration>
cool,好像完成了我们的要求。
下面为我们的CustomSectionWithChildElement外面再加一层SectionGroup.
publicclassCustomSectionGroup:System.Configuration.ConfigurationSectionGroup
{
[ConfigurationProperty("customSectionA",IsRequired=true,IsKey=true)]
publicCustomSectionWithChildElementSectionA
{
get{returnbase.Sections["customSectionA"]asCustomSectionWithChildElement;}
set
{
this.Sections.Add("customSectionA",value);
}
}
}
publicclassCustomSectionGroupWithChildElementBroker
{
privateCustomSectionWithChildElementcustomSection=null;
publicvoidInsertCustomSectionGroup()
{
customSection=newCustomSectionWithChildElement();
customSection.ChildSectionA=newCustomSectionElementA();
customSection.ChildSectionB=newCustomSectionElementB();
CustomSectionGroupsectionGroup=newCustomSectionGroup();
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if(config.GetSectionGroup("customSectionGroup")==null)
config.SectionGroups.Add("customSectionGroup",sectionGroup);
sectionGroup.SectionA=customSection;
config.Save(ConfigurationSaveMode.Minimal);
}
publicintGetCustomSectionChildAID()
{
System.Configuration.Configurationconfig=ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
CustomSectionWithChildElementcswe=config.GetSection("customSectionGroup/customSectionA")asCustomSectionWithChildElement;
returncswe.ChildSectionA.ChildID;
}
}
测试一下:
[TestMethod]
publicvoidTestCustomSectionGroupWithChildElement()
{
CustomSectionGroupWithChildElementBrokercweb=newCustomSectionGroupWithChildElementBroker();
cweb.InsertCustomSectionGroup();
Assert.AreEqual(1,cweb.GetCustomSectionChildAID());
}
没问题,看下现在的app.config,是不是更加结构化了:
<configuration>
<configSections>
<sectionGroupname="MySectionGroup">
<sectionname="MyFirstSection"type="System.Configuration.DictionarySectionHandler"/>
<sectionname="MySecondSection"type="System.Configuration.DictionarySectionHandler"/>
</sectionGroup>
<sectionGroupname="customSectionGroup"type="Tonnie.Configuration.Library.CustomSectionGroup,Tonnie.Configuration.Library,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
<sectionname="customSectionA"type="Tonnie.Configuration.Library.CustomSectionWithChildElement,Tonnie.Configuration.Library,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
</sectionGroup>
</configSections>
<MySectionGroup>
<MyFirstSection>
<addkey="First"value="FirstSection"/>
</MyFirstSection>
<MySecondSection>
<addkey="Second"value="SecondSection"/>
</MySecondSection>
</MySectionGroup>
<customSectionGroup>
<customSectionA>
<childSectionAchildId="1"childValue="ChildA"/>
<childSectionBchildId="2"childValue="ChildB"/>
</customSectionA>
</customSectionGroup>
</configuration>
3高级使用
到目前为止可能大家对app.config有了一定的认识了,我们自己可以不断的去扩展.NETFramework提供给我们的类,从SectionGroup,Section,ElementCollection,Element从上自下的一级一级的组装成符合工程化项目配置文件需要的形式。当遇到可能配置元素的类型属性差不多时,可以抽象出一个base类来。比如可以抽象出Section这一层面的base类,或者ElementCollection,Element这一层的抽象类(可以是抽象的泛型类)来。同时增加泛型来更好的支持扩展。
相关文章推荐
- unity默认资源的文件夹
- Android 之回调的简单用法
- android编码时的细节进行优化内存
- iOS同一种页面布局加载不同的页面数据的数据刷新
- Unity视频播放的各种实现方式汇总
- pull解析一些特殊类型的XML文件
- uitableview cell上加载webview
- Android:interpolator
- Android View.onMeasure方法的理解
- Unity3d脚本改变GameObject的Material(二)
- Android实现TextView部分文本监听单击事件
- Android IPC机制(二)用Messenger进行进程间通信【转】
- MVC和MVP在App中的对比分析以及实际应用
- 微信URL Scheme
- Android Studio 代码多屏查看
- IOS 框架页面跳转、Appdelegate.m控制返回rootVC
- java ipone 微信昵称emoji表情保存失败 无法存入数据库
- Android中SharedPreferences和序列化结合保存对象数据
- 移动端HTML5点击事件闪现灰色背景解决方案
- 修改navigationController的背景色和隐藏navigationController下黑线