web-dev-qa-db-ja.com

C#でカスタム構成ファイルを読み取る(Framework 4.0)

Framework 4.0でC#のアプリケーションを開発しています。

私のアプリケーションでは、app.configファイルではない個別の構成ファイルを作成したいと思います。構成ファイルには、製品用に開発したカスタム構成セクションが含まれています。

ConfigSourceを使用してapp.configからこのファイルを参照したくありません。

実行時に読み込み、コンテンツを読みたいです。

私が言いたいことの例は、log4net.configファイルに構成を書き込むことができるlog4netです。

フレームワークに存在するコードをmimcsするコードを書くことなく、誰でもそれを行う方法を助けることができますか?

更新:

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
    }
    

コードでは、コンストラクターの入力パラメーターを検証してログファイルがnullではなく、ファイルが存在することを確認するために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
        }
    }
37
Koby Mizrahy
 // 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);

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

21
Kaido

過去にNiniを使用しました- http://nini.sourceforge.net/manual.php これにより、カスタム構成ファイルの読み取り/書き込みが可能になります(XML/Ini/Registry/.Config)実行時。

お役に立てれば。

7
christofr

構成に関する私のアドバイスは、独自のコンポーネントを作成してそれを読み取ることです。
ある時点で、データベースやWebサービスなどの別のソースから設定を取得することに決めた場合、開発が容易になる可能性があります。
この種類の抽象化は、構成のモックやテスト容易性の向上にも役立ちます(.NETフレームワークではうまくいかないこと)。
構成形式としてXMLを使用している場合、Linq to XMLを使用することをお勧めします。
読みやすく、XMLファイルの解析に使用しやすいです。

2
the_drow

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>
2
nittuj

または NameValueCollection を使用して簡単に

0
Damian