在.NET中,app.config和web.config是应用程序的配置文件。我们可以自定义配置节来实现读取和写入完全自定义的配置信息,使配置信息更一目了然。
将一系列相关的配置保存在配置文件中,可以定义configSections,可以使用NameValueSectionHandler、DictionarySectionHandler来处理集合,但是在写入的时候比较麻烦(如果谁知道比较简便的办法,烦请告诉我,谢谢 ),而且在有的地方需要比较复杂的配置的时候,还是自定义配置来得容易。
配置文件中的元素称为基本 XML 元素或节(Section)。基本元素只是具有相关属性(如果有)的简单 XML 标记。节最简单的形式与基本元素一致。而复杂的节可以包括一个或多个基本元素、元素的集合以及其他节。
可以用ConfigurationSection和IConfigurationSectionHandler来扩展自定义配置,但后者已经被2.0框架否决。因此,我在这里使用ConfigurationSection来实现一个自定义配置。
ConfigurationElement 用作表示 XML 配置元素(如 ConfigurationSection)的类的基类。可以扩展 ConfigurationElement 类,以使其表示 ConfigurationSection 节中的配置元素。也可以创建一个 ConfigurationElement 元素的 ConfigurationElementCollection 集合。
配置文件如下:
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
configSections
>
<
section
name
="fileTypes"
type
="CustomConfig.ConfigSection, CustomConfig"
/>
</
configSections
>
<
fileTypes
>
<
files
>
<
clear
/>
<
add
file
="htm"
desc
="html page"
/>
<
add
file
="html"
desc
="html page"
/>
<
add
file
="asp"
desc
="Active Server Page file"
/>
</
files
>
</
fileTypes
>
</
configuration
>
我们需要3个类来实现这个自定义配置。
继承自ConfigurationSection的类管理配置节,因为要保存集合,所以要扩展ConfigurationElement和ConfigurationElementCollection两个类,下面看代码:
ConfigHandler.cs
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Configuration;
namespace
CustomConfig
...
{ public class ConfigSection: ConfigurationSection ... { ConfigElement element; public ConfigSection() ... { element = new ConfigElement(); } [ConfigurationProperty(" files " )] public ConfigElementCollection FileTypes ... { get ... { ConfigElementCollection types = (ConfigElementCollection) base [ " files " ]; return types; } } protected override void DeserializeSection(System.Xml.XmlReader reader) ... { base .DeserializeSection(reader); } protected override string SerializeSection(ConfigurationElement parentElement, string name, ConfigurationSaveMode saveMode) ... { return base .SerializeSection(parentElement, name, saveMode); } } }
ConfigElement.cs
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Configuration;
namespace
CustomConfig
...
{ public class ConfigElement : ConfigurationElement ... { public ConfigElement() ... { } public ConfigElement( string fileType) ... { FileType = fileType; } public ConfigElement( string fileType, string description) ... { FileType = fileType; Description = description; } [ConfigurationProperty(" file " )] public string FileType ... { get ... { return ( string ) this [ " file " ]; } set ... { this [ " file " ] = value; } } [ConfigurationProperty(" desc " )] public string Description ... { get ... { return ( string ) this [ " desc " ]; } set ... { this [ " desc " ] = value; } } protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) ... { base .DeserializeElement(reader, serializeCollectionKey); } protected override bool SerializeElement(System.Xml.XmlWriter writer, bool serializeCollectionKey) ... { return base .SerializeElement(writer, serializeCollectionKey); } protected override bool IsModified() ... { return base .IsModified(); } } }
ConfigElementCollection.cs
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Configuration;
namespace
CustomConfig
...
{ public class ConfigElementCollection : ConfigurationElementCollection ... { public ConfigElementCollection() ... { ConfigElement element = (ConfigElement)CreateNewElement(); Add(element); } protected override ConfigurationElement CreateNewElement() ... { return new ConfigElement(); } protected override object GetElementKey(ConfigurationElement element) ... { return ((ConfigElement)element).FileType; } public override ConfigurationElementCollectionType CollectionType ... { get ... { // return base.CollectionType; return ConfigurationElementCollectionType.AddRemoveClearMap; } } public new string AddElementName ... { get ... { return base .AddElementName; } set ... { base .AddElementName = value; } } public new string ClearElementName ... { get ... { return base .ClearElementName; } set ... { base .AddElementName = value; } } public new string RemoveElementName ... { get ... { return base .RemoveElementName; } } public new int Count ... { get ... { return base .Count; } } public ConfigElement this [ int index] ... { get ... { return (ConfigElement)BaseGet(index); } set ... { if (BaseGet(index) != null ) BaseRemoveAt(index); BaseAdd(index, value); } } public new ConfigElement this [ string name] ... { get ... { return (ConfigElement)BaseGet(name); } } public int IndexOf(ConfigElement element) ... { return BaseIndexOf(element); } public void Add(ConfigElement element) ... { BaseAdd(element); } protected override void BaseAdd(ConfigurationElement element) ... { base .BaseAdd(element, false ); } public void Remove(ConfigElement element) ... { if (BaseIndexOf(element) >= 0 ) BaseRemove(element.FileType); } public void RemoveAt( int index) ... { BaseRemoveAt(index); } public void Remove( string name) ... { BaseRemove(name); } public void Clear() ... { BaseClear(); } } }
到这里已经实现了读取和写入自定义配置节了,使用时可以像这样:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Configuration;
namespace
CustomConfig
...
{ /**/ /// <summary> /// Custom Configuration Sample Program Startup /// You can find the reference on MSDN: /// http://msdn2.microsoft.com/zh-cn/library/system.configuration.configurationelement (VS.80).aspx /// </summary> class Program ... { static void Main( string [] args) ... { // open configuration Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); Console.WriteLine( " Raw XML data: " ); Console.WriteLine(config.Sections[ " fileTypes " ].SectionInformation.GetRawXml()); // Read the config settings Console.WriteLine(Environment.NewLine + " Collections from config file: " ); ConfigSection files = config.Sections[ " fileTypes " ] as ConfigSection; foreach (ConfigElement element in files.FileTypes) ... { Console.WriteLine( string .Format( " {0,8} : {1,-20} " , element.FileType, element.Description)); } // write settings // seems very easy? ConfigElement elem = new ConfigElement( " js " , " Javascript File " ); Console.WriteLine(Environment.NewLine + " Add a new element: " + elem.FileType); files.FileTypes.Add(elem); config.Save(ConfigurationSaveMode.Full); /**/ /////////////////////////////////////////////////////////////////////////// Console.Write(Environment.NewLine + " Press ENTER to exit. " ); Console.Read(); } } }
至此,你也可以实现许多自己的自定义配置了。
本文中的源代码可以从http://download.youkuaiyun.com/source/269958 下载,然后Build就可以看到效果了。
(更正说明:之前的ConfigHandler类现在改为了ConfigSection,这样更适合.NET 2.0,Handler更像是从IConfigurationSectionHandler类继承而来,但已经被否决,所以改为ConfigSection更优)