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

StackOverflow https://stackoverflow.com/questions/4738

Вопрос

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top