Как динамически загрузить отдельный файл настроек приложения и объединить его с текущими настройками?
Есть вопросы, относящиеся к чтению настроек из отдельного конфигурационного файла и других подобных ему, но мой вопрос касается настроек свойств приложения (т.е. <MyApplication.Properties.Settings>
- см. файл XML ниже) и как загрузить их динамически. Я попробовал метод в этом посте, который включал обновление всего раздела appSettings основного файла конфигурации, но моя адаптация вызвала исключения, потому что я не заменял раздел appSettings:
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
// Have tried the other ConfigurationUserLevels to no avail
config.AppSettings.File = myRuntimeConfigFilePath;
config.Save(ConfigurationSaveMode.Modified); // throws ConfigurationErrorsException
ConfigurationManager.RefreshSection("userSettings");
ConfigurationErrorsException.Message: "Корневой элемент должен соответствовать имени раздела, ссылающегося на файл, 'appSettings' (C:\myFile.xml строка 2)." Файл:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<MyApplication.Properties.Settings>
<setting name="SineWaveFrequency" serializeAs="String">
<value>6</value>
</setting>
<setting name="SineWaveAmplitude" serializeAs="String">
<value>6</value>
</setting>
</MyApplication.Properties.Settings>
</userSettings>
</configuration>
Есть ли способ импортировать значения из этого файла в MyApplication.Properties.Settings.Default
класс, с каркасом, обрабатывающим всю десериализацию XML, как это происходит при загрузке файла конфигурации при запуске приложения?
2 ответа
Ну, это работает:
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
public static class SettingsIO
{
internal static void Import(string settingsFilePath)
{
if (!File.Exists(settingsFilePath))
{
throw new FileNotFoundException();
}
var appSettings = Properties.Settings.Default;
try
{
var config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.PerUserRoamingAndLocal);
string appSettingsXmlName =
Properties.Settings.Default.Context["GroupName"].ToString();
// returns "MyApplication.Properties.Settings";
// Open settings file as XML
var import = XDocument.Load(settingsFilePath);
// Get the whole XML inside the settings node
var settings = import.XPathSelectElements("//" + appSettingsXmlName);
config.GetSectionGroup("userSettings")
.Sections[appSettingsXmlName]
.SectionInformation
.SetRawXml(settings.Single().ToString());
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("userSettings");
appSettings.Reload();
}
catch (Exception) // Should make this more specific
{
// Could not import settings.
appSettings.Reload(); // from last set saved, not defaults
}
}
internal static void Export(string settingsFilePath)
{
Properties.Settings.Default.Save();
var config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.PerUserRoamingAndLocal);
config.SaveAs(settingsFilePath);
}
}
Метод экспорта создает файл, подобный следующему:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<MyApplication.Properties.Settings>
<setting name="SineWaveFrequency" serializeAs="String">
<value>1</value>
</setting>
<setting name="SineWaveAmplitude" serializeAs="String">
<value>100</value>
</setting>
<setting name="AdcShift" serializeAs="String">
<value>8</value>
</setting>
<setting name="ControlBitsCheckedIndices" serializeAs="String">
<value>0,1,2,3,5,6,7,8</value>
</setting>
<setting name="UpgradeSettings" serializeAs="String">
<value>False</value>
</setting>
</MyApplication.Properties.Settings>
</userSettings>
</configuration>
Метод import анализирует этот файл, берет все внутри узла, помещает этот XML-файл в файл user.config в соответствующем разделе, а затем перезагружает Properties.Settings.Default, чтобы получить эти значения из нового файла user.config.
Решение, предложенное Пат:
// Get the whole XML inside the settings node
var settings = import.XPathSelectElements("//" + appSettingsXmlName);
возвращается null
, Я изменил это на
var settings = import.Element("configuration").Element("userSettings").Element(appSettingsXmlName);
config.GetSectionGroup("userSettings")
.Sections[appSettingsXmlName]
.SectionInformation
.SetRawXml(settings.ToString());
И это работает отлично.