Подтвердить что ты не робот

Прочитать пользовательский файл конфигурации на С# (Framework 4.0)

Я разрабатываю приложение на С# в Framework 4.0.

В моем приложении я хотел бы создать отдельный файл конфигурации, который не является файлом app.config. Файл конфигурации содержит пользовательские разделы конфигурации, которые мы разработали для продукта.

Я не хочу ссылаться на этот файл из app.config с помощью configSource.

Я хочу загрузить его во время выполнения и прочитать его содержимое.

Пример того, что я имею в виду, это log4net, который позволяет вам записать конфигурацию в файле log4net.config.

Может ли кто-нибудь помочь, как это сделать без написания кода, который копирует код, который существует в рамках?

UPDATE:

на основе ответа от Kaido Я написал класс утилиты, который читает пользовательский файл конфигурации и имеет возможность обновлять содержимое Config при изменении файла в файловой системе.

Использование в этом классе выглядит следующим образом:

  • Получить содержимое файла конфигурации

    // 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 для проверки входного параметра конструктора, чтобы проверить, что файл журнала не является нулевым и что файл существует. Вы можете изменить код, чтобы сделать эти проверки встроенными в код (хотя я рекомендую использовать 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
        }
    }
4b9b3361

Ответ 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

Ответ 2

В прошлом я использовал Nini - http://nini.sourceforge.net/manual.php, который позволяет читать/записывать настраиваемые файлы конфигурации (XML/Ini/Registry/.Config) во время выполнения.

Надеюсь, что это поможет.

Ответ 3

Мой совет с настройкой - создать свой собственный компонент, чтобы его прочитать.
Это может облегчить разработку, если в какой-то момент вы решите, что получите конфигурацию из другого источника, такого как база данных или через веб-службу.
Такой вид абстракции также помогает вам издеваться над конфигурацией и повышает тестируемость (что-то, что платформа .NET не очень хорошо работает).
Если вы используете XML в качестве формата конфигурации, я предлагаю использовать Linq для XML.
Легче читать и использовать для анализа XML файлов.

Ответ 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());
    }

}

В первый раз при запуске приложения он создаст раздел конфигурации в файле [appxename].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>