读取C#中的自定义configuration文件(Framework 4.0)

我正在C#框架下开发一个应用程序4.0。

在我的应用程序中,我想创build不是app.config文件的单独的configuration文件。 configuration文件包含我们为产品开发的自定义configuration部分。

我不想从app.config使用configSource引用这个文件。

我想在运行时加载它并阅读它的内容。

我的意思就是log4net的一个例子,它允许你在log4net.config文件中写configuration。

任何人都可以帮助如何做到这一点,而无需编写代码来模拟框架中存在的代码?

更新:

基于Kaido的回答,我写了一个工具类,它读取自定义的configuration文件,并且能够在文件系统上的文件改变时刷新configuration内容。

这个类的用法如下:

  1. 获取configuration文件内容

    // Create configuration reader that reads the files once var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config"); var config = configFileReader.Config; // Do any action you want with the config object like: config.GetSection("my.custom.section"); // or, var someVal = config.AppSettings.Settings["someKey"]; 
  2. configuration文件更改时收到通知

     // Create configuration reader that notifies when the configuraiton file changes var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config", true); // Register to the FileChanged event configFileReader.FileChanged += MyEventHandler; ... private void MyEventHanler(object sender, EventArgs e) { // You can safely access the Config property here, it is already contains the new content } 

在代码中,我使用PostSharp来validation构造函数input参数,以validation日志文件不是空的,并且文件存在。 您可以更改代码以使代码中的内联validation(尽pipe我build议使用PostSharp将应用程序分离到各个方面)。

这里是代码:

  using System; using System.Configuration; using System.IO; using CSG.Core.Validation; namespace CSG.Core.Configuration { /// <summary> /// Reads customer configuration file /// </summary> public class CustomConfigurationFileReader { // By default, don't notify on file change private const bool DEFAULT_NOTIFY_BEHAVIOUR = false; #region Fields // The configuration file name private readonly string _configFileName; /// <summary> /// Raises when the configuraiton file is modified /// </summary> public event System.EventHandler FileChanged; #endregion Fields #region Constructor /// <summary> /// Initialize a new instance of the CustomConfigurationFileReader class that notifies /// when the configuration file changes. /// </summary> /// <param name="configFileName">The full path to the custom configuration file</param> public CustomConfigurationFileReader(string configFileName) : this(configFileName, DEFAULT_NOTIFY_BEHAVIOUR) { } /// <summary> /// Initialize a new instance of the CustomConfigurationFileReader class /// </summary> /// <param name="configFileName">The full path to the custom configuration file</param> /// <param name="notifyOnFileChange">Indicate if to raise the FileChange event when the configuraiton file changes</param> [ValidateParameters] public CustomConfigurationFileReader([NotNull, FileExists]string configFileName, bool notifyOnFileChange) { // Set the configuration file name _configFileName = configFileName; // Read the configuration File ReadConfiguration(); // Start watch the configuration file (if notifyOnFileChanged is true) if(notifyOnFileChange) WatchConfigFile(); } #endregion Constructor /// <summary> /// Get the configuration that represents the content of the configuration file /// </summary> public System.Configuration.Configuration Config { get; set; } #region Helper Methods /// <summary> /// Watch the configuraiton file for changes /// </summary> private void WatchConfigFile() { var watcher = new FileSystemWatcher(_configFileName); watcher.Changed += ConfigFileChangedEvent; } /// <summary> /// Read the configuration file /// </summary> public void ReadConfiguration() { // Create config file map to point to the configuration file var configFileMap = new ExeConfigurationFileMap { ExeConfigFilename = _configFileName }; // Create configuration object that contains the content of the custom configuration file Config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None); } /// <summary> /// Called when the configuration file changed. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ConfigFileChangedEvent(object sender, FileSystemEventArgs e) { // Check if the file changed event has listeners if (FileChanged != null) // Raise the event FileChanged(this, new EventArgs()); } #endregion Helper Methods } } 
  // Map the roaming configuration file. This // enables the application to access // the configuration file using the // System.Configuration.Configuration class ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap(); configFileMap.ExeConfigFilename = roamingConfig.FilePath; // Get the mapped configuration file. Configuration config = ConfigurationManager.OpenMappedExeConfiguration( configFileMap, ConfigurationUserLevel.None); 

http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx

在过去,我使用了Nini – http://nini.sourceforge.net/manual.php ,它允许您在运行时读取/写入自定义configuration文件(XML / Ini / Registry / .Config)。

希望这可以帮助。

我对configuration的build议是创build自己的组件来阅读它。
如果在某个时候您会决定从另一个数据库(如数据库或Web服务)获取configuration,则可能会缓解开发。
这种抽象也可以帮助你模拟configuration并提高可testing性(.NET框架根本无法做到)。
如果你使用XML作为configuration格式,我build议使用Linq to XML。
读取和使用来parsingXML文件更容易。

你可以尝试你的需求的Cinchoo框架 。 它通过代码优先的方法简化了开发工作。 如下定义一个类,

 namespace HelloWorld { #region NameSpaces using System; using Cinchoo.Core.Configuration; #endregion NameSpaces [ChoConfigurationSection("sample")] public class SampleConfigSection : ChoConfigurableObject { #region Instance Data Members (Public) [ChoPropertyInfo("name", DefaultValue="Mark")] public string Name; [ChoPropertyInfo("message", DefaultValue="Hello World!")] public string Message; #endregion } static void Main(string[] args) { SampleConfigSection sampleConfigSection = new SampleConfigSection(); Console.WriteLine(sampleConfigSection.ToString()); } } 

第一次运行应用程序时,它将在[appexename] .xml文件中创buildconfiguration部分,如下所示。 然后,对此文件所做的任何更改将被自动提取

 <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" /> </configSections> <sample> <add key="name" value="Mark" /> <add key="message" value="Hello World!" /> </sample> </configuration> 

或者使用NameValueCollection更容易