App.config
昨天基本弄清config的使用之后,再看WP的API,晕了。结果WP不支持system.configuration命名空间,这意味着想在WP上用App.config不大可能了。
WP具体支持API请查看
不过还是记录下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 <section name="appSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
4 <section name="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
1 private static volatile ConfigurationProperty s_propAppSettings;
2 private static volatile ConfigurationProperty s_propFile;
其跟App.config中映射的字段
1 ConfigurationProperty property = new ConfigurationProperty(null, typeof(KeyValueConfigurationCollection), null, ConfigurationPropertyOptions.IsDefaultCollection);
2 ConfigurationProperty property2 = new ConfigurationProperty("file", typeof(string), string.Empty, ConfigurationPropertyOptions.None);
1 s_propAppSettings = property;
2 s_propFile = property2;
属性暴露出来为:
file(attribute)
不作为元素:

1 [ConfigurationProperty("file", DefaultValue="")]
2 public string File
3 {
4 get
5 {
6 string str = (string) base[s_propFile];
7 if (str == null)
8 {
9 return string.Empty;
10 }
11 return str;
12 }
13 set
14 {
15 base[s_propFile] = value;
16 }
17 }

element:

1 [ConfigurationProperty("", IsDefaultCollection=true)]
2 public KeyValueConfigurationCollection Settings
3 {
4 get
5 {
6 return (KeyValueConfigurationCollection) base[s_propAppSettings];
7 }
8 }

对于不是嵌套的element,而是直接作为section的子节点集合,就照这样写,这样写没有在App.config的对应名字,看起来全是add元素(当然也可以有,后面会说明)
再来看看KeyValueConfigurationCollection这个集合继承自ConfigurationElementCollection
其中重要的两个方法:

1 protected override ConfigurationElement CreateNewElement()
2 {
3 return new KeyValueConfigurationElement();
4 }
5
6 protected override object GetElementKey(ConfigurationElement element)
7 {
8 return ((KeyValueConfigurationElement) element).Key;
9 }

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

1 private static readonly ConfigurationProperty _propKey = new ConfigurationProperty("key", typeof(string), string.Empty, ConfigurationPropertyOptions.IsKey | Configurat ionPropertyOptions.IsRequired);
2 private static readonly ConfigurationProperty _propValue = new ConfigurationProperty("value", typeof(string), string.Empty, ConfigurationPropertyOptions.None); 3 [ConfigurationProperty("key", Options=ConfigurationPropertyOptions.IsKey, DefaultValue="")]
4 public string Key
5 {
6 get
7 {
8 return (string) base[_propKey];
9 }
10 }
11 [ConfigurationProperty("value", DefaultValue="")]
12 public string Value
13 {
14 get
15 {
16 return (string) base[_propValue];
17 }
18 set
19 {
20 base[_propValue] = value;
21 }
22 }

具体到element的key,value了。这样我们也可以自定义节点了。
二.模仿appSettings做自己的setting
创建一个控制台应用和一个类库,在控制台中先添加system.configuration程序集的引用。然后我们写上自己想要的App.config的内容。如下

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3
8 <Songs ChannelId="1">
9 <add name="1.mp3" length="100" />
10 <add name="2.mp3" length="100" />
11 <add name="3.mp3"/>
12 <add length="200"/>
13 </Songs>
14
15 </configuration>

这样算是定义好了一些配置,其中有些song配置使用了默认的值。
但是为了使Songs这个Section工作起来,我们也需要像Appsettings一样添加自定义Section,我们添加 <configSections>元素,再在里面添加Section,添加好,完整如下

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <configSections>
7 <section name="Songs" type="ConfigLib.SongsSection,ConfigLib"/>
8 </configSections>
9
10 <Songs ChannelId="1">
11 <add name="1.mp3" length="100" />
12 <add name="2.mp3" length="100" />
13 <add name="3.mp3"/>
14 <addlength="200"/>
15 </Songs>
16
17 </configuration>

其中ConfigLib为我们一开始添加的库的名字 ConfigLib.SongsSection为要映射到的类。
接下看看SongsSection类。
同样在ConfigLib这个Lib中添加system.configuration这个dll,然后使SongsSection这个类去继承ConfigurationSection类
1 namespace ConfigLib
2 {
3 public class SongsSection:ConfigurationSection
4 {
5 }
6 }
由于我们的appSettings的子节点都是数据的单个点,总共是一个集合,所以我们还要一个集合类用来存放所有的song.这个集合要继承ConfigurationElementCollection类
1 namespace ConfigLib
2 {
3 class Songcollection:ConfigurationElementCollection
4 {
5 }
6 }
但是这样是编译不过的,因为ConfigurationElementCollection类里有2个标注为abstract的方法需要我们子类来实现,先让它编译通过,如下

1 public class Songcollection:ConfigurationElementCollection
2 {
3 protected override ConfigurationElement CreateNewElement()
4 {
5 throw new NotImplementedException();
6 }
7 protected override object GetElementKey(ConfigurationElement element)
8 {
9 throw new NotImplementedException();
10 }
11 }

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

1 namespace ConfigLib
2 {
3 public class SongsSection:ConfigurationSection
4 {
5 private readonly ConfigurationProperty collectionproperty = new ConfigurationProperty(null, typeof(Songcollection), null, ConfigurationPropertyOptions.IsDefaultCollection);
6 [ConfigurationProperty("",IsDefaultCollection=true)]
7 public Songcollection SongCollection
8 {
9 get
10 {
11 return (Songcollection)this[collectionproperty];
12
13 }
14 }
15 [ConfigurationProperty("ChannelId", IsKey = false, DefaultValue = "-1")]
16 public int ChannelId
17 {
18 get
19 {
20 return (int)this["ChannelId"];
21 }
22 }
23 }
24 }

其中SongCollection属性的写法很像appSettings的写法。
接下来看看Songcollection这个集合类最简单的写法:

1 namespace ConfigLib
2 {
3 public class Songcollection:ConfigurationElementCollection
4 {
5 protected override ConfigurationElement CreateNewElement()
6 {
7 return new SongElement();
8 }
9 protected override object GetElementKey(ConfigurationElement element)
10 {
11 return ((SongElement)element).Name;
12 }
13
14 }
15 }

集合类的很多属性我们使用父类的,字面意思都比较好理解,其中GetElementKey是为这个集合指定关键字的,有点像数据库中的Key,这个Key不能重复,并且我们可以通过
这个Key获得集合中的元素(SongElement).
集合中主要是Element,Element基本就和XML中Element一样,SongElement这个类如下,用这个类(SongElement)定义的变量就是(app.config)XML中的Element,而不是Attribute,(类中的所有简单类型都在Attribute中出现)

1 namespace ConfigLib
2 {
3 public class SongElement:ConfigurationElement
4 {
5 [ConfigurationProperty("name",IsKey=true,DefaultValue="default.mp3")]
6 public string Name
7 {
8 get
9 {
10 return (string)this["name"];
11 }
12 }
13 [ConfigurationProperty("length", IsKey = false, DefaultValue = "-1")]
14 public int Length
15 {
16 get
17 {
18 return (int)this["length"];
19 }
20 }
21 }
22 }

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

1 public SongElement this[int index]
2 {
3 get
4 {
5 return (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 <section name="Songs" type="ConfigLib.SongsSection,ConfigLib"/>
5 </configSections>
6 <Songs ChannelId="1">
7 <song name="1.mp3" length="100" />
8 <song name="2.mp3" length="100" />
9 <song name="3.mp3"/>
10 <song length="200"/>
11 </Songs>
12 </configuration>

把add改成了song,这样顺眼一点
那仅仅只要在集合类中添加:

1 protected override string ElementName
2 {
3 get
4 {
5 return "song";
6 }
7 }
8 public override ConfigurationElementCollectionType CollectionType
9 {
10 get
11 {
12 return ConfigurationElementCollectionType.BasicMap;
13 }
14 }

就可以了
如果App.config改为下面这样:

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <configSections>
4 <section name="Songs" type="ConfigLib.SongsSection,ConfigLib"/>
5 </configSections>
6 <Songs ChannelId="1">
7 <special_special_song specialsongname="special_1.mp3"/>
8 <specialsongs>
9 <specialsong specialsongname="special_2.mp3"/>
10 <specialsong specialsongname="special_3.mp3"/>
11 <specialsong specialsongname="special_4.mp3"/>
12 </specialsongs>
13 <song name="1.mp3" length="100" />
14 <song name="2.mp3" length="100" />
15 <song name="3.mp3"/>
16 <song length="200"/>
17 </Songs>
18 </configuration>

一样的道理,加一个SpecialSongElement类和容纳这个类的集合SpecialSongCollection,然后再在Section中做添加即可,在section类中,第一个
<special_special_song specialsongname="special_1.mp3"/>对应:

1 [ConfigurationProperty("special_special_song", IsKey = false)]
2 public SpecialSongElement SpecialSong
3 {
4 get
5 {
6 return (SpecialSongElement)this["special_special_song"];
7 }
8 }

而集合
<specialsongs>对应:

1 [ConfigurationProperty("specialsongs", IsKey = false, IsDefaultCollection = false)]
2 public SpecialSongCollection SpecialSongs
3 {
4 get
5 {
6 return (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了。
App.config的更多相关文章
- WCF中,通过C#代码或App.config配置文件创建ServiceHost类
C# static void Main(string[] args) { //创建宿主的基地址 Uri baseAddress = new Uri("http://localhost:808 ...
- C# 读取app.config配置文件 节点键值,提示 "配置系统未能初始化" 错误的解决方案
新建C#项目,在app.config中添加了appSettings项,运行时出现"配置系统未能初始化"的错误,MSDN里写到,如果配置文件中包含 configSections 元素 ...
- 使用App.config管理数据库连接
程序的数据库连接字符串可以保持在程序的配置文件App.config中,便于管理. 将配置文件添加至解决方案: 添加连接信息: <?xml version="1.0"?> ...
- App.config“配置系统未能初始化” 异常解决 C#
System.Configuration.ConfigurationManager.AppSettings["user"]; 时出现“配置系统未能初始化” 错误 解决办法: 如果配 ...
- Visual Studio 2013 Unit Test Project App.config文件设置方法
开放中经常会要做单元测试,新的项目又没有单元测试项目,怎么才能搭建一个单元测试项目呢? 下面跟我四步走,如有错误之处,还请指正! 1.添加项目 2.添加配置文件 新建app.config文件,注意不是 ...
- C# 对 App.config的appSettings节点数据进行加密
.NET平台下的Winform和Asp.net的配置文件默认都是明文保存的,本文使用的是.Net自身如何加密配置文件,不包含自定义的加密规则 但.Net是提供了直接对配置文件加密的功能的,使用.Net ...
- .NET 多个程序配置文件合并到主app.config
.NET 多个程序配置文件合并到主app.config
- 【转载】App.config/Web.config 中特殊字符的处理
写一个网站,遇到一个问题,发布以后,提示错误,但是即使打开错误提示(在web.config中打开),还是只提示错误,没提示什么地方错误,这让我知道了:是webconfig本身的错误,经过排除,是链接字 ...
- 说说Web.Config与App.Config
说到web.config和app.config大家都很熟悉,我们都叫他们配置文件,平时用的多,注意的少.两个有啥区别呢,很简单,一句话:如果是web程序,如webform项目类型和mvc项目类型就是w ...
- App.Config详解及读写操作
App.Config详解及读写操作 App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而 ...
随机推荐
- Android: ADT 23.0.2
http://pan.baidu.com/s/1gdnBUUJ 版权声明:本文博主原创文章.博客,未经同意不得转载.
- ExtJS4 动态生成grid出口excel(纯粹的接待)
搜索相当长的时间,寻找一些样本,因为我刚开始学习的原因,大多数人不知道怎么用.. 他曾在源代码.搞到现在终于实现了主下载.. 表的采集格不重复下载一个小BUG,一个使用grid初始化发生的BUG 以下 ...
- 4.mysql数据库创建,表中创建模具模板脚本,mysql_SQL99标准连接查询(恩,外部连接,全外连接,交叉连接)
mysql数据库创建,表创建模等模板脚本 -- 用root用户登录系统,运行脚本 -- 创建数据库 create database mydb61 character set utf8 ; -- ...
- Linux了解进程的地址空间
供Linux了解虚拟内存,非常好的引导了.原文链接:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26683523&i ...
- 架构设计之设计模式 (一) 适配器(Adapter)---提高复用性
简介 简介是为了描述一下该模式是干嘛用的,为了让不了解该模式的人看了之后也有一些新的认识. 本文章分为两部分,第一部分主要介绍适配器模式:第二部分介绍该模式与相近模式的异同. 下午一直在讨论设计模式, ...
- BestCoder-Round#33
写在前面 这是我第一次做BestCoder, 熟悉的外观BestCoder模式. BC上不仅能看到英文, 背部Chinese view是中文题目 交的次数是会影响得分的. 所以有了把握再交. 至少例子 ...
- 交易应用-运行多个SQL声明
事务具有原子性.要么不运行.要么全运行.一旦成功运行永久保存.而这些正是因为事务的原子性和对数据库的持久性形成的.下面是一个关于统一给数据库中的数据改动的批量操作,利用到事务. TODO:批量改动数据 ...
- 细说 ASP.NET Cache 及其高级用法【转】
阅读目录 开始 Cache的基本用途 Cache的定义 Cache常见用法 Cache类的特点 缓存项的过期时间 缓存项的依赖关系 - 依赖其它缓存项 缓存项的依赖关系 - 文件依赖 缓存项的移除优先 ...
- C#关于图片的相关处理
public class ImageHelper { /// <summary> /// 图片转换成字节流 /// </summary> /// <param name= ...
- 无废话WCF入门教程三[WCF的宿主]
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...