Прочитать пользовательский файл конфигурации на С# (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
}
}
Ответы
Ответ 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>
Ответ 5
Или используйте NameValueCollection проще