【问题标题】:Read custom configuration file in C# (Framework 4.0)读取 C# 中的自定义配置文件(Framework 4.0)
【发布时间】:2011-09-14 13:48:48
【问题描述】:

我正在使用 C# 在 Framework 4.0 下开发应用程序。

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

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

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

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

任何人都可以在不编写模仿框架中存在的代码的代码的情况下帮助如何做到这一点吗?

更新:

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

该类中的用法如下:

  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
    }
    

在代码中,我使用 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
        }
    }

【问题讨论】:

    标签: c# configuration configuration-files


    【解决方案1】:
     // 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

    【讨论】:

    • 能否添加一个如何从config 对象中提取数据的示例?
    • 点击链接查看完整示例。您可以在 Configuration 对象上调用 GetSection 方法并将结果转换为强类型的自定义 ConfigurationSection(在示例中称为 ConsoleSection)
    【解决方案2】:

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

    希望这会有所帮助。

    【讨论】:

    • 有趣。感谢您的提醒。
    • 您好,感谢您的回答。我想坚持使用标准的 .net 配置。下面的答案解决了我遇到的问题
    【解决方案3】:

    我对配置的建议是创建您自己的组件来阅读它。
    如果您在某个时候决定从另一个来源(如数据库或 Web 服务)获取配置,这可能会简化开发。
    这种抽象还可以帮助您模拟配置并提高可测试性(.NET 框架根本无法做到这一点)。
    如果您使用 XML 作为配置格式,我建议使用 Linq to XML。
    它更易于阅读和使用来解析 XML 文件。

    【讨论】:

    • (+1) 同意。我已经阅读了几个文档,并且没有太大帮助。似乎这些类被设计为具有尽可能多的安全性,但是,这个想法适得其反。
    【解决方案4】:

    您可以根据需要尝试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>
    

    【讨论】:

      【解决方案5】:

      或者使用NameValueCollection更方便

      【讨论】:

        猜你喜欢
        • 2016-03-27
        • 2012-06-18
        • 2017-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多