Плагин для использования собственного app.config

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

Мое приложение-хостинг использует файл app.config для некоторых значений по умолчанию для исполняющей сборки (которая является службой Windows).

Каждый плагин должен иметь возможность загружать собственные настройки из отдельного файла настроек плагина, потому что хост не должен быть осведомлен о настройках плагина. В проекте плагина я также добавил файл app.config(с некоторыми настройками и строкой соединения), чтобы я мог создать экземпляр класса Properties.Settings и использовать его свойства в коде плагина.

Проблема в том, что я изменяю настройки в app.config плагина (который создается как plugin.dll.config). Я не вижу этих изменений в самом плагине, который по-прежнему использует настройки времени разработки.

Есть ли способ загрузить настройки app.config в каждом плагине, чтобы сгенерированный класс Properties.Settings работал? Если нет, есть другой способ загрузить файл настроек на основе app.config в плагин? Я планирую добавить метод LoadConfiguration в интерфейсе IPlugin, чтобы каждый плагин загружал его собственные настройки.

Ответ 1

Вы работаете против архитектуры app.config. Вы получаете один файл app.config для исполняемого файла (EXE, а не DLL). Исполняемый файл запускает, создает AppDomain, а затем загружает MyApp.exe.config. Вы можете добавлять объекты app.config в Visual Studio, но они игнорируются для библиотек DLL. Я думаю, что вы хотите вручную скопировать XML из dll.config и вставить его в уровень приложения app.config. (Я уверен, что есть способ автоматизировать это с помощью TeamBuild или некоторых таких.) Затем переопределенные значения будут доступны для вашего класса Properties.Settings.

Ответ 2

Будет что-то вроде ConfigurationManager.OpenMappedExeConfiguration здесь? Вы можете создать объект конфигурации, считывая значения из определенного файла.

Ответ 3

Я предпочитаю создавать и использовать плагин типа IConfigManager. Задача состоит в том, чтобы абстрагироваться от сохранения конфигурации. Вы получаете экземпляр его через инъекцию зависимости. Таким образом, реализация IConfigManager может загружать настройки из нескольких файлов .config, из сети, db или любого другого источника. Я также использую его для предоставления значений по умолчанию на основе пользователя, машины и/или приложения, которые могут быть отменены пользователем, например. цвет фона, шрифт и т.д.

Другими преимуществами этого метода являются то, что настройки могут сохраняться согласованным образом во всех плагинах - без необходимости использования плагинов, место, где ваш плагин сохраняет свои настройки, может меняться прозрачно (от .config до другого) и, наконец, IConfigManager можно высмеять во время модульного тестирования, чтобы имитировать различные ситуации.

Я надеюсь, что это поможет.

Ответ 4

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

В наших плагинах мы используем несколько экземпляров клиентов службы WCF. Чистота этих сервисов заключается в том, что они поставляются с разделами app.config, которые вы можете использовать для настройки поведения, типа сервиса, безопасности и т.д. И т.д.

Теперь, когда мы загружаем наши плагины, эти разделы отсутствуют в config, и поэтому правильные конечные точки не могут быть найдены. Разумеется, мы могли бы установить их в коде, но такой тип позволяет устанавливать другие параметры конфигурации по мере необходимости. Возможно, мы захотим реализовать ws-security.

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

Я подумал о создании небольшого инструмента, который объединил бы конфигурацию "master" со всеми конфигурациями, размещенными в поддире проекта, и заменил файл .exe.config этим. Я думаю, что это сработает, но мне было интересно, не предоставляет ли .NET более лучшие варианты. Несколько приложений AppDomains - это не то, что будет работать, потому что плагины должны взаимодействовать (модель поставщика/потребителя) друг с другом, и мы не хотим переключаться на удаленный доступ только из-за этой проблемы.

Обновление: я исправил большинство проблем с помощью ConfigurationManager, чтобы открыть существующие конфиги для чтения приложений. Что касается клиентов WCF; вы можете загрузить конфигурацию конечной точки/привязки для сервера и клиента, как показано здесь: http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx

Ответ 5

Вы можете сделать каждый подключаемый модуль, прочитав его собственный ConfigurationSection, а затем в главном файле конфигурации используйте параметр ConfigSource, чтобы указать на внешний файл. (См. Ссылку для получения дополнительной информации)

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

Ответ 6

Обычно я предпочитаю избегать беспорядка в app.config, создавая выделенный Xml файл, который хост обрабатывает с настройками плагина также внутри. Xml будет выглядеть примерно так:

<root>
    <Settings>
        Here where anything specific to the app goes.
    </Settings>
    <plugins>
        <plugin type="mylibrary.myclass">
            Here I let the plugin serialize itself however it wants to.
        </plugin>
    </plugins>
</root>

Затем приложение-хостинг создает плагин из атрибута type и проверяет, реализует ли класс ISerializable; если это произойдет, то плагин будет десериализоваться. Немного страшно иметь встроенные плагины с настройками приложения, но если вы загрузите подстроку плагина Xml в новый XmlReader, вам не придется беспокоиться о ошибке в плагине от чтения слишком далеко в строке Xml.