2011-06-14 63 views
34

我正在C#框架4.0下開發應用程序。在C#中(Framework 4.0)讀取自定義配置文件

在我的應用程序中,我想創建單獨的配置文件,它不是app.config文件。配置文件包含我們爲產品開發的自定義配置部分。

我不想使用configSource從app.config引用此文件。

我想在運行時加載它並閱讀它的內容。

我的意思是log4net的一個例子,它允許您在log4net.config文件中寫入配置。

任何人都可以幫助如何做到這一點,而無需編寫代碼來模擬框架中存在的代碼?

UPDATE:

基於答案從海道我寫的實用工具類,它讀取自定義配置文件,並有刷新配置內容的能力當上了文件系統更改文件。

這個類中的用法如下:

  1. 獲取配置文件內容

    // 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. 獲得通知時配置文件更改

    // 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 
    } 
    

在c ode我使用PostSharp爲了驗證構造函數輸入參數來驗證日誌文件不是空的,並且文件存在。您可以更改代碼以在代碼中進行內聯驗證(儘管我建議使用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 
     } 
    } 

回答

16
// 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

+0

謝謝!它解決了我所遇到的問題並解決了問題。 – 2011-06-15 06:10:16

+0

你可以添加一個如何從'config'對象中提取數據的例子嗎? – 2013-09-13 17:58:23

+0

請查看完整示例的鏈接。您可以調用Configuration對象上的GetSection方法,並將結果轉換爲強類型的自定義ConfigurationSection(在本例中稱爲ConsoleSection) – Kaido 2013-09-16 09:25:47

2

我與配置的建議是創建自己的組件來閱讀。
如果在某些時候您會決定從另一個數據源(如數據庫或Web服務)獲取配置,它可能會緩解開發。
這種抽象還可以幫助您嘲弄配置並提高可測試性(.NET框架根本無法做到)。
如果您使用XML作爲配置格式,我建議使用Linq to XML。
閱讀和分析XML文件更容易。

+0

(+1)同意。我已經閱讀了幾個文檔,並沒有太多幫助。看起來這些類的設計儘可能地具有更高的安全性,但是這個想法卻不合時宜。 – umlcat 2014-09-18 17:39:40

6

在過去,我使用Nini - http://nini.sourceforge.net/manual.php,它允許您在運行時讀取/寫入自定義配置文件(XML/Ini/Registry/.Config)。

希望這會有所幫助。

+0

有趣。謝謝你的提醒。 – 2011-06-14 12:49:22

+0

嗨,謝謝你的回答。我想堅持使用標準的.net配置。下面的答案解決了我的問題 – 2011-06-15 06:09:32

2

您可以嘗試Cinchoo framework您的需求。它通過代碼優先的方法簡化了開發工作。定義如下一類,

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如下文件。然後任何對此文件所做的更改將被自動提取

<?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> 
相關問題