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

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

Я хотел бы использовать пользовательский ConfigurationSection, и для страниц ASP.NET это отлично работает. Но когда компонент вызывается через COM interop со страницы классического 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);
Комментарии (3)

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

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

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

Пример:

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

Больше деталей может быть найдено в этот блог.

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

using(AppConfig.Change(tempFileName))
{
    // tempFileName is used for the app config during this context
}
Комментарии (3)

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

Есть два способа, которые я нашел, чтобы обойти это. Первый, который мне не нравится, заключается в повторной реализации системных групп секций путем копирования их из machine.config в ваш собственный web.config, например.



    <section name="smtp" type="System.Net.Configuration.SmtpSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

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

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

Комментарии (1)

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

Комментарии (0)

Принятый ответ неправильный!!

Это бросает следующее исключение на доступ к собственности AppSettings:

Неспособный бросить объект типа ' Система. Конфигурация. DefaultSection' напечатать ' Система. Конфигурация. AppSettingsSection'.

Вот правильное решение:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Комментарии (2)

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

A. ЧИСТЫЙ компонент Библиотеки классов быть назвал/принял в MS Word. Обеспечить конфигурацию оценивает моему компоненту, я создал winword.exe.config в C:\Program Files\Microsoft Office\OFFICE11 folder. Вам необходимо читать, ценности конфигураций как Вы делают в Традиционном.NET.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];
Комментарии (0)

Поскольку ASP.NET используют WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;
Комментарии (0)

Это должно добиться цели:

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

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

Комментарии (0)

Использование обработка XML:

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

// can call root.Elements(...)
Комментарии (0)