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

读取C#(Framework 4.0)中的自定义配置文件,c#,configuration,configuration-files,C#,Configuration,Configuration Files,我正在Framework 4.0下用C#开发一个应用程序 在我的应用程序中,我希望创建单独的配置文件,而不是app.config文件。配置文件包含我们为产品开发的自定义配置部分 我不想使用configSource从app.config引用此文件 我想在运行时加载它并读取它的内容 我的意思的一个例子是log4net,它允许您在log4net.config文件中写入配置 有人能帮助我们在不编写代码的情况下实现这一点吗 更新: 根据Kaido的回答,我编写了一个实用程序类,该类读取自定义配置文件,并能

我正在Framework 4.0下用C#开发一个应用程序

在我的应用程序中,我希望创建单独的配置文件,而不是app.config文件。配置文件包含我们为产品开发的自定义配置部分

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

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

我的意思的一个例子是log4net,它允许您在log4net.config文件中写入配置

有人能帮助我们在不编写代码的情况下实现这一点吗

更新:

根据Kaido的回答,我编写了一个实用程序类,该类读取自定义配置文件,并能够在文件系统上的文件更改时刷新配置内容

此类中的用法如下所示:

  • 获取配置文件内容

    // 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"];
    
  • 在配置文件更改时获取通知

    // 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来验证构造函数输入参数,以验证日志文件是否为null以及该文件是否存在。您可以更改代码,使这些验证内联到代码中(尽管我建议使用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
            }
        }
    
    使用系统;
    使用系统配置;
    使用System.IO;
    使用CSG.Core.Validation;
    命名空间CSG.Core.Configuration
    {
    /// 
    ///读取客户配置文件
    /// 
    公共类CustomConfigurationFileReader
    {
    //默认情况下,不通知文件更改
    private const bool DEFAULT\u NOTIFY\u behavior=false;
    #区域字段
    //配置文件名
    私有只读字符串_configFileName;
    /// 
    ///修改配置文件时引发
    /// 
    public event System.EventHandler文件已更改;
    #端域字段
    #区域构造函数
    /// 
    ///初始化通知的CustomConfigurationFileReader类的新实例
    ///当配置文件更改时。
    /// 
    ///自定义配置文件的完整路径
    公共CustomConfigurationFileReader(字符串configFileName)
    :此(配置文件名、默认\u通知\u行为)
    {            
    }        
    /// 
    ///初始化CustomConfigurationFileReader类的新实例
    /// 
    ///自定义配置文件的完整路径
    ///指示配置文件更改时是否引发FileChange事件
    [验证参数]
    公共CustomConfigurationFileReader([NotNull,FileExists]字符串配置文件名,bool notifyOnFileChange)
    {
    //设置配置文件名
    _configFileName=configFileName;
    //读取配置文件
    ReadConfiguration();
    //启动监视配置文件(如果notifyOnFileChanged为true)
    如果(notifyOnFileChange)
    WatchConfigFile();
    }
    #端域构造函数
    /// 
    ///获取表示配置文件内容的配置
    /// 
    public System.Configuration.Configuration配置
    {
    得到;
    设置
    }
    #区域辅助方法
    /// 
    ///查看配置文件中的更改
    /// 
    私有void WatchConfigFile()
    {
    var-watcher=新的FileSystemWatcher(_-configFileName);
    watcher.Changed+=ConfigFileChangedEvent;
    }
    /// 
    ///读取配置文件
    /// 
    public void ReadConfiguration()
    {
    //创建配置文件映射以指向配置文件
    var configFileMap=new ExeConfigurationFileMap
    {
    ExeConfigFilename=\u configFileName
    };
    //创建包含自定义配置文件内容的配置对象
    Config=ConfigurationManager.OpenMappedExeConfiguration(configFileMap,ConfigurationUserLevel.None);
    }        
    /// 
    ///配置文件更改时调用。
    /// 
    /// 
    /// 
    私有void ConfigFileChangedEvent(对象发送方、文件系统目标)
    {
    //检查文件更改事件是否具有侦听器
    if(FileChanged!=null)
    //提出事件
    FileChanged(这是新的EventArgs());
    }
    #端域辅助方法
    }
    }
    
    我的配置建议是创建您自己的组件来读取它。
    如果在某个时候您决定从另一个来源(如数据库或web服务)获取配置,则可能会简化开发。
    这种抽象还可以帮助您模拟配置并提高可测试性(这是.NET framework根本做不好的事情)。
    如果您使用XML作为配置格式,我建议使用Linq to XML。

    它更易于读取和解析XML文件。

    过去我使用过Nini,它允许您在运行时读取/写入自定义配置文件(XML/Ini/Registry/.Config)

    希望这有帮助

     // 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);
    

    或使用更简单的

    您可以尝试满足您的需要。它通过代码优先的方法简化了开发工作。定义一个类,如下所示,

    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()); } }
    <?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>