Использование ConfigurationManager для загрузки конфигурации из произвольного местоположения

Я разрабатываю компонент доступа к данным, который будет использоваться на веб-сайте, который содержит сочетание классических страниц ASP и ASP.NET и нуждается в хорошем способе управления настройками его конфигурации.

Я хотел бы использовать обычай ConfigurationSectionи для страниц ASP.NET это прекрасно работает. Но когда компонент вызывается через COM-взаимодействие с классической страницы ASP, он не работает в контексте запроса ASP.NET и поэтому не знает о web.config.

Есть ли способ рассказать ConfigurationManager просто загрузить конфигурацию с произвольного пути (например, ..\web.config если моя сборка находится в /bin папка)? Если есть, то я думаю, что мой компонент может вернуться к этому, если по умолчанию ConfigurationManager.GetSection возвращается null для моего пользовательского раздела.

Любые другие подходы к этому приветствуются!

8 ответов

Решение

Попробуй это:

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 объект, чтобы сбросить его обратно в исходное состояние. С помощью этого решения вы можете сохранить временную конфигурацию приложения:

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}

Ответ Измаила, как правило, работает, однако я обнаружил одну проблему: OpenMappedMachineConfiguration кажется, потерял ваши унаследованные группы разделов из machine.config. Это означает, что вы можете получить доступ к вашим собственным пользовательским разделам (а это все, что требуется OP), но не к нормальным системным разделам. Например, этот код не будет работать:

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 не зарегистрирован как SectionGroup, поэтому он практически недоступен по обычным каналам.

Есть два способа обойти это. Первое, что мне не нравится, - это повторная реализация групп системных разделов, скопировав их из 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. Но, похоже, это работает для меня.

Принятый ответ неверен!!

Выдает следующее исключение при доступе к свойству 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);

В дополнение к ответу Измаила, метод OpenMappedMachineConfiguration() всегда будет возвращать Configuration объект. Таким образом, чтобы проверить, загружен ли он, вы должны проверить HasFile свойство true означает, что оно было получено из файла.

Я предоставил значения конфигурации для словосочетания.nET Compoent следующим образом.

Компонент.NET Class Library, вызываемый / размещаемый в MS Word. Чтобы предоставить значения конфигурации для моего компонента, я создал файл winword.exe.config в папке C:\Program Files\Microsoft Office\OFFICE11. Вы должны быть в состоянии прочитать значения конфигурации, как Вы делаете в Традиционном.NET.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];

Это должно сделать трюк:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "newAppConfig.config);

Источник: https://www.codeproject.com/Articles/616065/Why-Where-and-How-of-NET-Configuration-Files

Для 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(...)
Другие вопросы по тегам