Заставить ConfigurationManager перезагрузить все разделы

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

  1. Загрузчик создает файл конфигурации.
  2. Загрузчик инициализирует новый домен приложений с новым файлом конфигурации в качестве файла конфигурации.
  3. В результате новый домен приложений настроен на использование нового файла конфигурации, и все работает нормально.

Мы хотели бы отойти от этого подхода, состоящего из нескольких доменов приложений; он добавляет уровень сложности, особенно когда речь идет о неуправляемых библиотеках и другом устаревшем коде.

При переходе к одному домену приложений рабочий процесс изменится на:

  1. Загрузчик создает файл конфигурации.
  2. Загрузчик объединяет файл конфигурации в свой собственный файл конфигурации.
  3. Загрузчик обновляет кеш ConfigurationManager.
  4. Загрузчик запускает основное приложение в том же домене приложений.

Похоже, ConfigurationManager кеширует разделы в памяти. Так, например, если я прочитал AppSettings до шага №3, я должен позвонить: ConfigurationManager.RefreshSection("appSettings"); Фактически, я должен убедиться, что любой раздел, который был использован загрузчиком, обновлен.

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


person Szymon Rozga    schedule 06.07.2009    source источник


Ответы (1)


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

Похоже, стандартного способа сделать это не существует. Однако, получив доступ к внутренним полям и типам класса ConfigurationManager, я смог перечислить все загруженные разделы. Вот как я это сделал:

private static IEnumerable<string> GetLoadedSections()
{
    // s_configSystem can be null if the ConfigurationManager is not properly loaded. Accessing the AppSettings *should* do the trick.
    var appSettings = ConfigurationManager.AppSettings;

    FieldInfo s_configSystemField = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
    object s_configSystem = s_configSystemField.GetValue(null);
    FieldInfo _completeConfigRecordField = s_configSystem.GetType().GetField("_completeConfigRecord", BindingFlags.NonPublic | BindingFlags.Instance);
    object _completeConfigRecord = _completeConfigRecordField.GetValue(s_configSystem);
    FieldInfo _sectionRecordsField = _completeConfigRecord.GetType().GetField("_sectionRecords", BindingFlags.NonPublic | BindingFlags.Instance);
    Hashtable _sectionRecords = (Hashtable)_sectionRecordsField.GetValue(_completeConfigRecord);
    return _sectionRecords.Keys.OfType<string>();
}

Раздел "system.diagnostics" вроде всегда загружается. Также загружается раздел "appSettings", так как я должен получить к нему доступ, чтобы он работал стабильно.

Это работает на моем компьютере (.NET 4.5), но поскольку он полагается на внутренние компоненты, он может сломаться в любое время, если Microsoft решит изменить реализацию класса ConfigurationManager.

person Nicolas V.    schedule 03.01.2014