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

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

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

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

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

Ответов (9)

Решение

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

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

Для 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(...)

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

Я считаю, что это лучшее решение для загрузки файла конфигурации нетривиального пути, в частности лучший способ прикрепить файл конфигурации к 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
}

Это должно помочь:

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

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

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

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

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

Ответ 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>

Я не уверен, что само веб-приложение после этого будет работать правильно, но вы можете правильно получить доступ к sectionGroups.

Второе решение - вместо этого открыть ваш 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. Но, похоже, это работает для меня.

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

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

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