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

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

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

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

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

Ответ 1

Попробуйте следующее:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);

Ответ 2

Другое решение - переопределить путь к файлу конфигурации среды по умолчанию.

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

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);

Пример:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");

Более подробную информацию можно найти на в этом блоге.

Кроме того, этот другой ответ имеет отличное решение, в комплекте с кодом для обновления конфигурацию приложения и объект IDisposable до reset обратно в исходное состояние. С этим решение, вы можете сохранить временную конфигурацию приложения:

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

Ответ 3

Ответ Ishmaeel обычно работает, однако я обнаружил одну проблему, которая заключается в том, что использование 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!

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

Для ASP.NET используйте WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;

Ответ 7

Использовать обработку XML:

var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);

// can call root.Elements(...)