Загрузка Properties.Settings из другого файла во время выполнения
Есть ли способ загрузить настройки из другого файла, кроме файла по умолчанию App.config
файл во время выполнения? Я хотел бы сделать это после загрузки файла конфигурации по умолчанию.
Я использую Settings.Settings
GUI в Visual Studio для создания моего App.config
файл для меня. Конфигурационный файл выглядит примерно так:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="SnipetTester.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<SnipetTester.Properties.Settings>
<setting name="SettingSomething" serializeAs="String">
<value>1234</value>
</setting>
</SnipetTester.Properties.Settings>
</applicationSettings>
</configuration>
В коде я могу получить доступ к настройкам, как это:
Console.WriteLine("Default setting value: " + Properties.Settings.Default.SettingSomething);
Идея состоит в том, что при запуске приложения я должен иметь возможность указать файл конфигурации во время выполнения и заставить приложение загрузить файл конфигурации в Properties.Settings.Default
объект вместо использования по умолчанию app.config
файл. Форматы файлов конфигурации будут одинаковыми, но значения настроек будут другими.
Я знаю способ сделать это с ConfigurationManager.OpenExeConfiguration(configFile);
, Тем не менее, в тестах, которые я провел, он не обновляет Properties.Settings.Default
Объект для отражения новых значений из файла конфигурации.
Подумав об этом немного дольше, я смог придумать решение, которое мне больше нравится. Я уверен, что у него есть некоторые подводные камни, но я думаю, что это сработает для того, что мне нужно.
По сути, Properties.Settings
класс автоматически генерируется Visual Studio; он генерирует код для класса для вас. Я смог найти, где был сгенерирован код, и добавить несколько вызовов функций, чтобы загрузить файл конфигурации самостоятельно. Вот мое дополнение:
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
//Parses a config file and loads its settings
public void Load(string filename)
{
System.Xml.Linq.XElement xml = null;
try
{
string text = System.IO.File.ReadAllText(filename);
xml = System.Xml.Linq.XElement.Parse(text);
}
catch
{
//Pokemon catch statement (gotta catch 'em all)
//If some exception occurs while loading the file,
//assume either the file was unable to be read or
//the config file is not in the right format.
//The xml variable will be null and none of the
//settings will be loaded.
}
if(xml != null)
{
foreach(System.Xml.Linq.XElement currentElement in xml.Elements())
{
switch (currentElement.Name.LocalName)
{
case "userSettings":
case "applicationSettings":
foreach (System.Xml.Linq.XElement settingNamespace in currentElement.Elements())
{
if (settingNamespace.Name.LocalName == "SnipetTester.Properties.Settings")
{
foreach (System.Xml.Linq.XElement setting in settingNamespace.Elements())
{
LoadSetting(setting);
}
}
}
break;
default:
break;
}
}
}
}
//Loads a setting based on it's xml representation in the config file
private void LoadSetting(System.Xml.Linq.XElement setting)
{
string name = null, type = null, value = null;
if (setting.Name.LocalName == "setting")
{
System.Xml.Linq.XAttribute xName = setting.Attribute("name");
if (xName != null)
{
name = xName.Value;
}
System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs");
if (xSerialize != null)
{
type = xSerialize.Value;
}
System.Xml.Linq.XElement xValue = setting.Element("value");
if (xValue != null)
{
value = xValue.Value;
}
}
if (string.IsNullOrEmpty(name) == false &&
string.IsNullOrEmpty(type) == false &&
string.IsNullOrEmpty(value) == false)
{
switch (name)
{
//One of the pitfalls is that everytime you add a new
//setting to the config file, you will need to add another
//case to the switch statement.
case "SettingSomething":
this[name] = value;
break;
default:
break;
}
}
}
}
Код, который я добавил, выставляет Properties.Settings.Load(string filename)
функция. Функция принимает имя файла конфигурации в качестве параметра. Он проанализирует файл и загрузит все настройки, с которыми он столкнется, в файле конфигурации. Чтобы вернуться к исходной конфигурации, просто позвоните Properties.Settings.Reload()
,
Надеюсь, что это может помочь кому-то еще!
3 ответа
Это зависит от типа приложения:
- Веб-приложение и приложение Windows - используйте атрибут configSource xml, если вы хотите хранить файлы конфигурации в той же папке (или подпапках), что и приложение
- Создайте поставщик настроек, а также внедрите IApplicationSettingsProvider. Образцы здесь и здесь. Вам также может понадобиться использовать интерфейс IConfigurationManagerInternal для замены менеджера конфигурации.NET по умолчанию. При реализации провайдера не забывайте различать пользовательские настройки и настройки приложения и перемещаемые профили.
Если вы хотите быстро начать работу, просто декомпилируйте класс LocalFileSettingsProvider (поставщик настроек по умолчанию) и измените его в соответствии с вашими потребностями (вы можете найти код для некоторых полезных функций и, возможно, потребуется реплицировать все классы, от которых он зависит).
Удачи
Посмотрите на использование ExeConfigurationFileMap и ConfigurationManager.OpenMappedExeConfiguration.
См. Раскрытие тайн конфигурации.Net 2.0.
ExeConfigurationFileMap позволяет вам специально настраивать точные имена путей к компьютерам, exe, роумингу и локальным файлам конфигурации, все вместе или по частям, при вызове OpenMappedExeConfiguration(). Вы не обязаны указывать все файлы, но все файлы будут идентифицированы и объединены при создании объекта конфигурации. При использовании OpenMappedExeConfiguration важно понимать, что все уровни конфигурации до уровня, который вы запрашиваете, всегда будут объединены. Если вы укажете пользовательский исполняемый файл и локальный файл конфигурации, но не укажете компьютер и перемещаемый файл, будут найдены машинный и перемещаемый файлы по умолчанию, которые будут объединены с указанными пользовательскими и пользовательскими файлами. Это может иметь неожиданные последствия, если указанные файлы не были должным образом синхронизированы с файлами по умолчанию.
Вы можете включить типы, так что вам не нужно каждый раз обновлять источник вручную.
`private void LoadSetting (настройка System.Xml.Linq.XElement) { string name = null, type = null; строковое значение = ноль;
if (setting.Name.LocalName == "setting")
{
System.Xml.Linq.XAttribute xName = setting.Attribute("name");
if (xName != null)
{
name = xName.Value;
}
System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs");
if (xSerialize != null)
{
type = xSerialize.Value;
}
System.Xml.Linq.XElement xValue = setting.Element("value");
if (xValue != null)
{
if (this[name].GetType() == typeof(System.Collections.Specialized.StringCollection))
{
foreach (string s in xValue.Element("ArrayOfString").Elements())
{
if (!((System.Collections.Specialized.StringCollection)this[name]).Contains(s))
((System.Collections.Specialized.StringCollection)this[name]).Add(s);
}
}
else
{
value = xValue.Value;
}
if (this[name].GetType() == typeof(int))
{
this[name] = int.Parse(value);
}
else if (this[name].GetType() == typeof(bool))
{
this[name] = bool.Parse(value);
}
else
{
this[name] = value;
}
}
}`