App.config的学习笔记

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

昨天基本弄清config的使用之后,再看WP的API,晕了。结果WP不支持system.configuration命名空间,这意味着想在WP上用App.config不大可能了。

WP具体支持API请查看

.net WP API

API reference

不过还是记录下App.config的使用。

有很大部分是从MSDN学来的,如果有人看我的这篇文章的话可以先去看看MSDN的相关章节 http://msdn.microsoft.com/en-us/library/system.configuration.configuration(v=vs.110).aspx

一.appSettings这个比较简单,也有很多资料讲到,在我的C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config中,有machine.config这个文件

有下面节选

1<configuration>2<configSections>3<sectionname="appSettings"type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"restartOnExternalChanges="false"requirePermission="false"/>4<sectionname="connectionStrings"type="System.Configuration.ConnectionStringsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"requirePermission="false"/>

后面长串省略………………

所以appSettings是一个section,当在配置文件中输入 <appSettings>节点时,系统会帮我们映射到System.Configuration.AppSettingsSection这个类中去,用reflector看看这个类

继承自ConfigurationSection

1PRivatestaticvolatileConfigurationProperty s_propAppSettings;2privatestaticvolatileConfigurationProperty s_propFile;

其跟App.config中映射的字段

1ConfigurationProperty property =newConfigurationProperty(null,typeof(KeyValueConfigurationCollection),null, ConfigurationPropertyOptions.IsDefaultCollection);2ConfigurationProperty property2 =newConfigurationProperty("file",typeof(string),string.Empty, ConfigurationPropertyOptions.None);

1s_propAppSettings =property;

2s_propFile = property2;

属性暴露出来为:

file(attribute)

不作为元素:

1[ConfigurationProperty("file", DefaultValue="")]2publicstringFile3{4get5{6stringstr = (string)base[s_propFile];7if(str ==null)8{9returnstring.Empty;10}11returnstr;12}13set14{15base[s_propFile] =value;16}17}

element:

1[ConfigurationProperty("", IsDefaultCollection=true)]2publicKeyValueConfigurationCollection Settings3{4get5{6return(KeyValueConfigurationCollection)base[s_propAppSettings];7}8}

对于不是嵌套的element,而是直接作为section的子节点集合,就照这样写,这样写没有在App.config的对应名字,看起来全是add元素(当然也可以有,后面会说明)

再来看看KeyValueConfigurationCollection这个集合继承自ConfigurationElementCollection

其中重要的两个方法:

1protectedoverrideConfigurationElement CreateNewElement()2{3returnnewKeyValueConfigurationElement();4}56protectedoverrideobjectGetElementKey(ConfigurationElement element)7{8return((KeyValueConfigurationElement) element).Key;9}

所以其实在每个Add中,Add的是KeyValueConfigurationElement,这个类的Key属性作为集合的关键字,再来看看KeyValueConfigurationElement类,这个类继承自ConfigurationElement

关键部分:

1privatestaticreadonlyConfigurationProperty _propKey =newConfigurationProperty("key",typeof(string),string.Empty, ConfigurationPropertyOptions.IsKey |Configurat ionPropertyOptions.IsRequired);2privatestaticreadonlyConfigurationProperty _propValue =newConfigurationProperty("value",typeof(string),string.Empty, ConfigurationPropertyOptions.None);

3[ConfigurationProperty("key", Options=ConfigurationPropertyOptions.IsKey, DefaultValue="")]4publicstringKey5{6get7{8return(string)base[_propKey];9}10}11[ConfigurationProperty("value", DefaultValue="")]12publicstringValue13{14get15{16return(string)base[_propValue];17}18set19{20base[_propValue] =value;21}22}

具体到element的key,value了。这样我们也可以自定义节点了。

二.模仿appSettings做自己的setting创建一个控制台应用和一个类库,在控制台中先添加system.configuration程序集的引用。然后我们写上自己想要的App.config的内容。如下

1<?xmlversion="1.0" encoding="utf-8"?>2<configuration>38<SongsChannelId="1">9<addname="1.mp3"length="100"/>10<addname="2.mp3"length="100"/>11<add name="3.mp3"/>12<addlength="200"/>13</Songs>1415</configuration>

这样算是定义好了一些配置,其中有些song配置使用了默认的值。

但是为了使Songs这个Section工作起来,我们也需要像Appsettings一样添加自定义Section,我们添加 <configSections>元素,再在里面添加Section,添加好,完整如下

1<?xml version="1.0" encoding="utf-8"?>2<configuration>3<configSections>7<sectionname="Songs"type="ConfigLib.SongsSection,ConfigLib"/>8</configSections>910<SongsChannelId="1">11<addname="1.mp3"length="100"/>12<addname="2.mp3"length="100"/>13<add name="3.mp3"/>14<addlength="200"/>15</Songs>1617</configuration>

其中ConfigLib为我们一开始添加的库的名字 ConfigLib.SongsSection为要映射到的类。

接下看看SongsSection类。

同样在ConfigLib这个Lib中添加system.configuration这个dll,然后使SongsSection这个类去继承ConfigurationSection类

1namespaceConfigLib2{3publicclassSongsSection:ConfigurationSection4{5}6}

由于我们的appSettings的子节点都是数据的单个点,总共是一个集合,所以我们还要一个集合类用来存放所有的song.这个集合要继承ConfigurationElementCollection类

1namespaceConfigLib2{3classSongcollection:ConfigurationElementCollection4{5}6}

但是这样是编译不过的,因为ConfigurationElementCollection类里有2个标注为abstract的方法需要我们子类来实现,先让它编译通过,如下

1publicclassSongcollection:ConfigurationElementCollection2{3protectedoverrideConfigurationElement CreateNewElement()4{5thrownewNotImplementedException();6}7protectedoverrideobjectGetElementKey(ConfigurationElement element)8{9thrownewNotImplementedException();10}11}

先不管实现,我们用这个Collection来装song.回到SongsSection类,我们可以使用上面的集合了,像appSettings那样,但要注意,我们为Songs这个Section添加了类似XML中属性(attribute)的channleid,由于这个不是Element,是个int类型(后面还有ConfigurationElement类),所以我们在类中属性(Property)中使用的时候这个的时候不会跑到element中去,它会乖乖在XML的属性位置。代码如下

1namespaceConfigLib2{3publicclassSongsSection:ConfigurationSection4{5privatereadonlyConfigurationProperty collectionproperty =newConfigurationProperty(null,typeof(Songcollection),null, ConfigurationPropertyOptions.IsDefaultCollection);6[ConfigurationProperty("",IsDefaultCollection=true)]7publicSongcollection SongCollection8{9get10{11return(Songcollection)this[collectionproperty];1213}14}15[ConfigurationProperty("ChannelId", IsKey =false, DefaultValue ="-1")]16publicintChannelId17{18get19{20return(int)this["ChannelId"];21}22}23}24}

其中SongCollection属性的写法很像appSettings的写法。

接下来看看Songcollection这个集合类最简单的写法:

1namespaceConfigLib2{3publicclassSongcollection:ConfigurationElementCollection4{5protectedoverrideConfigurationElement CreateNewElement()6{7returnnewSongElement();8}9protectedoverrideobjectGetElementKey(ConfigurationElement element)10{11return((SongElement)element).Name;12}1314}15}

集合类的很多属性我们使用父类的,字面意思都比较好理解,其中GetElementKey是为这个集合指定关键字的,有点像数据库中的Key,这个Key不能重复,并且我们可以通过

这个Key获得集合中的元素(SongElement).

集合中主要是Element,Element基本就和XML中Element一样,SongElement这个类如下,用这个类(SongElement)定义的变量就是(app.config)XML中的Element,而不是Attribute,(类中的所有简单类型都在Attribute中出现)

1namespaceConfigLib2{3publicclassSongElement:ConfigurationElement4{5[ConfigurationProperty("name",IsKey=true,DefaultValue="default.mp3")]6publicstringName7{8get9{10return(string)this["name"];11}12}13[ConfigurationProperty("length", IsKey =false, DefaultValue ="-1")]14publicintLength15{16get17{18return(int)this["length"];19}20}21}22}

为每个XML的attribute设置默认值,并且不为必须的,写App.config的时候保证Key(这里是歌的名字)不重复,如果需要通过索引访问song的集合,在集合中加如下索引器:

1publicSongElementthis[intindex]2{3get4{5return(SongElement)BaseGet(index);6}7}

由于集合是默认的AddClear类型,所以我们的XML元素(element)虽然存在,但是要写成add,clear形式,(如果有clear,clear写在哪,那么之前add过的元素就都不见了)

代码下载

App.config还可以改成下面这样

1<?xml version="1.0" encoding="utf-8"?>2<configuration>3<configSections>4<sectionname="Songs"type="ConfigLib.SongsSection,ConfigLib"/>5</configSections>6<SongsChannelId="1">7<songname="1.mp3"length="100"/>8<songname="2.mp3"length="100"/>9<songname="3.mp3"/>10<songlength="200"/>11</Songs>12</configuration>

把add改成了song,这样顺眼一点

那仅仅只要在集合类中添加:

1protectedoverridestringElementName2{3get4{5return"song";6}7}8publicoverrideConfigurationElementCollectionType CollectionType9{10get11{12returnConfigurationElementCollectionType.BasicMap;13}14}

就可以了

如果App.config改为下面这样:

1<?xml version="1.0" encoding="utf-8"?>2<configuration>3<configSections>4<sectionname="Songs"type="ConfigLib.SongsSection,ConfigLib"/>5</configSections>6<SongsChannelId="1">7<special_special_songspecialsongname="special_1.mp3"/>8<specialsongs>9<specialsongspecialsongname="special_2.mp3"/>10<specialsongspecialsongname="special_3.mp3"/>11<specialsongspecialsongname="special_4.mp3"/>12</specialsongs>13<songname="1.mp3"length="100"/>14<songname="2.mp3"length="100"/>15<songname="3.mp3"/>16<songlength="200"/>17</Songs>18</configuration>

一样的道理,加一个SpecialSongElement类和容纳这个类的集合SpecialSongCollection,然后再在Section中做添加即可,在section类中,第一个

<special_special_song specialsongname="special_1.mp3"/>对应:

1[ConfigurationProperty("special_special_song", IsKey =false)]2publicSpecialSongElement SpecialSong3{4get5{6return(SpecialSongElement)this["special_special_song"];7}8}

而集合

<specialsongs>对应:

1[ConfigurationProperty("specialsongs", IsKey =false, IsDefaultCollection =false)]2publicSpecialSongCollection SpecialSongs3{4get5{6return(SpecialSongCollection)this["specialsongs"];7}8}

注意IsDefaultCollection = false。这个SpecialSongCollection集合跟前面的集合基本一样。

最后的效果:

代码下载

如果有多个Section的时候可以考虑使用sectionGroup来给各个Section分组

像系统的C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config一样

还有虽然微软不提倡使用IConfigurationSectionHandler来解析Section,但是我觉得这个方法知道也不错,这个解析方法是把getsection中的section作为根XmlNode,传到接口实现的方法 public object Create(object parent, object configContext, System.Xml.XmlNode section)中

其中System.Xml.XmlNode section参数就是根xmlNode,然后就可以操作Xml了。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航