Как динамически загрузить отдельный файл настроек приложения и объединить его с текущими настройками?
Есть вопросы, касающиеся чтения настроек из отдельного конфигурационного файла и других подобных ему, но мой вопрос относится к настройкам свойств приложения (т. е. <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.Сообщение: "корневой элемент должен соответствовать имени раздела, ссылающегося на файл, "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>
Метод импорта анализирует этот файл, берет все внутри узла, помещает этот XML в пользователя.конфигурационный файл в соответствующем разделе, затем перезагружает свойства.Настройки.По умолчанию, чтобы захватить эти значения от нового пользователя.конфигурационный файл.
Решение, предложенное Пэтом:
// 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());