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

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

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

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

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

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


person Erik Beijer    schedule 08.05.2009    source источник


Ответы (6)


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

person Mike Post    schedule 08.05.2009
comment
Да, но в вопросе четко указано, что приложение не должно знать о настройках плагина. - person ChrisF; 08.05.2009
comment
Верно, однако я был бы удовлетворен, если бы я мог каким-то образом динамически вводить настройки из плагина в основной файл настроек app.config во время выполнения. Проблема здесь в том, что мне также нужна глава о настройке строки подключения в файлах app.config из моих плагинов, поскольку почти все они работают в базах данных SQL Server. - person Erik Beijer; 08.05.2009
comment
Если каждый плагин был создан в собственном домене приложения (как правило, это было бы неплохо, если бы это было видно из других сообщений на SO), то вы могли бы убедить его загрузить другой файл конфигурации для нового AppContext. - person Colin Desmond; 08.05.2009
comment
Да, я знаю, но поскольку мои плагины должны иметь возможность взаимодействовать друг с другом (посредством использования событий между плагинами поставщика и потребителя), вещи должны быть сериализованы и, таким образом, иметь возможность общаться через границы домена приложений. - person Erik Beijer; 08.05.2009

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

person Colin Desmond    schedule 08.05.2009
comment
Другая проблема, которая мешает этому работать, заключается в том, что у вас будет экземпляр Configuration, но сгенерированный класс Properties.Settings не будет работать. - person Erik Beijer; 08.05.2009

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

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

Надеюсь, это поможет.

person Lee Oades    schedule 19.05.2009
comment
Меня заинтриговал такой подход. Не могли бы вы опубликовать пример или ссылку на пример? - person HitLikeAHammer; 14.09.2009
comment
Привет, Рик, я не уверен, что смогу втиснуть в этот комментарий много примеров. У меня нет ссылки на что-либо конкретное для этого ответа - я мог бы написать сообщение в блоге, если бы у меня был блог. Есть ли часть из того, что я сказал, о которой вы хотели бы узнать больше? Я посмотрю, смогу ли я создать где-нибудь блог и написать об этом, но это будет не быстро. Ваше здоровье. - person Lee Oades; 16.09.2009

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

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

person HitLikeAHammer    schedule 14.09.2009

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

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

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

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

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

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

person Jasper    schedule 12.06.2009
comment
Знаете ли вы, что можно ссылаться на внешний файл .config из основного app.config / web.config? Таким образом, вы можете сохранить настройки плагина в отдельном файле и просто добавить ссылку на основную конфигурацию. Вы все равно должны каким-то образом зарегистрировать плагины, поэтому я не считаю это большим делом. - person Aaronaught; 27.12.2009

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

<root>
    <Settings>
        Here's 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.

person Community    schedule 24.08.2010