zoukankan      html  css  js  c++  java
  • App.config的学习笔记

    昨天基本弄清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:WindowsMicrosoft.NETFrameworkv4.0.30319Config中,有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:WindowsMicrosoft.NETFrameworkv4.0.30319Configmachine.config一样

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

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

  • 相关阅读:
    int、bigint、smallint 和 tinyint
    SQL Server 2005中修改 Server Collation的方法
    BCP 数据导入问题 Unix系统中的文本文件换行符引发的问题
    如何在不提升用户权限的情况下,使普通用户执行xp_cmdshell存储过程
    【转】分析SQL Server计划缓存
    很多年过去了
    SQL日志收缩
    【转】sql server 测试中一些常看的指标和清除缓存的方法
    反射相关
    js获取UserControl内容,避免拼html的麻烦
  • 原文地址:https://www.cnblogs.com/07lyt/p/4008418.html
Copyright © 2011-2022 走看看