Использование ConfigurationManager для загрузки конфигурации из произвольного места
-
08-06-2019 - |
Вопрос
Я разрабатываю компонент доступа к данным, который будет использоваться на веб-сайте, содержащем смесь классических страниц ASP и ASP.NET, и мне нужен хороший способ управления параметрами конфигурации.
Я хотел бы использовать пользовательский ConfigurationSection
, и для страниц ASP.NET это работает отлично.Но когда компонент вызывается через COM-взаимодействие с классической страницы ASP, компонент не запускается в контексте запроса ASP.NET и, следовательно, не имеет информации о web.config.
Есть ли способ сообщить ConfigurationManager
чтобы просто загрузить конфигурацию по произвольному пути (например. ..\web.config
если моя сборка находится в /bin
папка)?Если есть, то я думаю, что мой компонент может вернуться к этому, если значение по умолчанию ConfigurationManager.GetSection
возвращает null
для моего пользовательского раздела.
Любые другие подходы к этому приветствуются!
Решение
Попробуй это:
System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
Другие советы
Другое решение — переопределить путь к файлу конфигурации среды по умолчанию.
Я считаю, что это лучшее решение для загрузки файла конфигурации по нетривиальному пути, в частности, лучший способ прикрепить файл конфигурации к dll.
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);
Пример:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");
Более подробную информацию можно найти на этот блог.
Кроме того, этот другой ответ имеет отличное решение, в комплекте с кодом для обновления конфигурации приложения и IDisposable
объект, чтобы вернуть его в исходное состояние.С помощью этого решения вы можете сохранить Themary App Config Scoped:
using(AppConfig.Change(tempFileName))
{
// tempFileName is used for the app config during this context
}
Ответ Измаила обычно работает, однако я обнаружил одну проблему: использование OpenMappedMachineConfiguration
кажется, вы теряете унаследованные группы разделов из Machine.config.Это означает, что вы можете получить доступ к своим собственным настраиваемым разделам (это все, что нужно ОП), но не к обычным системным разделам.Например, этот код не будет работать:
ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup; // returns null
По сути, если вы наденете часы на configuration.SectionGroups
, вы увидите, что system.net не зарегистрирован как группа секций, поэтому он практически недоступен по обычным каналам.
Я нашел два способа обойти это.Первое, что мне не нравится, — это повторная реализация групп системных разделов, скопировав их из Machine.config в ваш собственный web.config, например
<sectionGroup name="system.net" type="System.Net.Configuration.NetSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<sectionGroup name="mailSettings" type="System.Net.Configuration.MailSettingsSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="smtp" type="System.Net.Configuration.SmtpSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</sectionGroup>
Я не уверен, что после этого само веб-приложение будет работать правильно, но вы сможете правильно получить доступ к группам разделов.
Второе решение — вместо этого открыть ваш web.config как конфигурацию EXE, что в любом случае, вероятно, ближе к его предполагаемой функции:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = strConfigPath };
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup; // returns valid object!
Осмелюсь сказать, что ни один из приведенных здесь ответов, ни мой, ни ответ Измаила, не использует эти функции в полной мере так, как задумали дизайнеры .NET.Но, похоже, это работает для меня.
В дополнение к ответу Измаила, метод OpenMappedMachineConfiguration()
всегда будет возвращать Configuration
объект.Поэтому, чтобы проверить, загрузилось ли оно, вам следует проверить HasFile
свойство, где true означает, что оно получено из файла.
Я предоставил значения конфигурации для компонента .nET, размещенного в Word, следующим образом.
Компонент библиотеки классов .NET, вызываемый/размещенный в MS Word.Чтобы предоставить значения конфигурации моему компоненту, я создал winword.exe.config в папке C:\Program Files\Microsoft Office\OFFICE11.Вы должны иметь возможность читать значения конфигурации, как в традиционном .NET.
string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
Принятый ответ неверен!
При доступе к свойству AppSettings выдается следующее исключение:
Невозможно привести объект типа «System.Configuration.DefaultSection» к типу «System.Configuration.AppSettingsSection».
Вот правильное решение:
System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Для ASP.NET используйте WebConfigurationManager:
var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Используйте обработку XML:
var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);
// can call root.Elements(...)
Это должно помочь:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "newAppConfig.config);
Источник : https://www.codeproject.com/Articles/616065/Why-Where-and-How-of-NET-Configuration-Files