Мне кажется, для большинства приложений это немного оверкилл.
Когда мы делали один проект с плагинами, то просто грузили все dll-ки из папки plugins и искали в них классы с нашим кастомным [MyPluginAttribute] и реализующие нужный интерфейс.
Естественно, всё было в пределах общего домена, на этом мы теряли безопасность и стабильность приложения, но из плюсов получали простоту реализации и дебага + скорость.
о! я нисколько не претендую на то, что предложенный мной подход самый удачный из возможных. Но в стоявшей когда-то задаче было необходимо показывать пользователю описание модуля, на основании которого он принимал решение о целесообразности использования модуля. Т.е. процесс загрузки сборки надо было оттянуть до последнего. Самым очевидным решение стало размещение описания в файле. Плюс использование файла дало еще некоторые преимущества (например возможность контроля целостности модуля).
вообще, было бы интересно почитать решения на основе Mono Cecil или даже MEF. Т.к. про первое слышу впервые, а второе появилось позже реализации описанной в статье идеи.
хм… очень может быть, что я чего-то не понимаю в работе с атрибутами, но на сколько мне известно, для получения атрибута класса необходимо произвести загрузку сборки в память. Плюс, возможно, что модуль требует наличие дополнительных библиотек, анализировать которые в поисках нужного атрибута, пустая трата времени.
Просто с атрибутами меньше возни, больше сокрыто и соответственно разработка модулей проще. В случае командной разработки думаю это важнее. Да и один раз подготовка, потом работает быстро.
«MEF умеет грузить модули только в тот же AppDomain.»
Это не совсем так. Под MEF — расширяемая архитектура. Из коробки он этого не умеет, но и только.
«как быть если плагины нужно уметь выгружать?»
Написать свой ExportProvider или Catalog (я, извините, точно уже не помню).
«Или нужно дать возможность сторонним разработчикам писать эти плагины?»
А это-то как связано?
Но речь-то даже не об этом, а о том, что статья о реализации плагинной архитектуры в .net без (хотя бы) слов «мы посмотрели на MEF, он вот так не умеет, поэтому сделали свое» выглядит странно.
«Написать свой ExportProvider или Catalog (я, извините, точно уже не помню).»
Можно так. Но это автоматически обозначает что нужно разбираться во внутренностях довольно большого фреймворка. Тут уже нужно серьезно подумать, не проще ли написать легковесную плагинную систему под собственные требования, либо найти фрейворк который подходит под требования.
«А это-то как связано?»
Стабильность и безопасность. Чужому коду лучше жить в отдельном AppDomain.
«Статья о реализации плагинной архитектуры в .net без (хотя бы) слов «мы посмотрели на MEF, он вот так не умеет, поэтому сделали свое» выглядит странно.»
С этим согласен. Всегда сначала стоит искать готовые решения :)
«Чего далеко ходить: pwlodek.blogspot.com/2011/07/isolating-mef-components.html »
За ссылку спасибо. Но там автор сам говорит что это proof of concept, а не продакшн код. Коммуникация плагинов через WCF — это оверкилл :) Если бы на MEF была бы отлаженная реализация плагинов с изоляцией AppDomain, я бы с радостью воспользовался. Но сейчас вот на одном из проектов как-раз ситуация, что мы похоже откатываемся с MEF на самописный вариант (ну или может т.н. MAF).
«Но это автоматически обозначает что нужно разбираться во внутренностях довольно большого фреймворка.»
Не надо. Это стандартная точка расширения.
У меня есть мнение, что разобраться в ней несколько проще, чем написать свою систему плагинов. И уж тем более мне кажется, что если не хватает квалификации в ней разобраться, то лучше свой велосипед не изобретать.
«Стабильность и безопасность. Чужому коду лучше жить в отдельном AppDomain.»
Чужому коду лучше жить в другом процессе. А еще лучше — в чужом сервисе.
Все, очевидно, зависит от задач и ситуаций.
«Коммуникация плагинов через WCF — это оверкилл»
Зато надежно и очевидно.
«Но сейчас вот на одном из проектов как-раз ситуация, что мы похоже откатываемся с MEF на самописный вариант (ну или может т.н. MAF).»
Не очень понимаю, чем цельный самописный вариант надежнее MEF, расширенного самописным кодом. Ну, хозяин-барин, тут ничего больше не скажешь.
задачи получения контекста приложения передо мной не вставало, поэтому указанную Вами проблему я решать даже не пытался. Увы.
Что же до IoC, то я не понимаю как они помогут решить проблему управления загрузкой сборок?
жаль, что мне попалась последняя статья раньше. За нее отдельное личное спасибо! Но в целом, на сколько я понял, идея о регистрации модулей в файле присутствует и там.
Статья хороша комментариями, узнал про MEF и прочее. Сам сделал похожее решение, только имена классов отличались, прямо смешно как похоже получилось :). Только я кэш строил, а не манифесты.
начитался в комментах про MEF и возникло несколько вопросов:
1. правильно ли я понимаю, что в MEF 1.0 нет возможности в рантайме подключать модули, которые неизвестны исполняемому коду? Типа рефлексии. Ну не могу я знать заранее, какие модули будут использоваться.
И второй вопрос, не про MEF:
2. Чтобы не грузить несколько одну и ту же библиотеку, можно ли написать поверх неё обёртку, подключать как обычный плагин. Сам же плагин будет работать на основе Синглтона. А раз домен приложения один, то и создавать несколько экземпляров, а от того и грузить одну и туже библиотеку не придется. В качестве примера COM-библиотеки Microsoft.Interopl.Office. Word, Excel…
1. Наоборот, все системы плагинов как раз и нацелены на ситуацию, когда к приложению подключаются произвольные модули, о которых оно в момент компиляции не знает. Приложению нужно знать лишь интерфейс подключения.
2. В одном AppDomain сборки (библиотеки) не дублируются. Одна сборка загружается только один раз.
Синглтон работает на другом уровне, не со сборками, а с классами (объектами). Это понятия из разных областей.
1. Так вот почитал я статью от уважаемого XaocCPS, там получается, что код, который импортирует модуль (подключает к себе), уже знает о существовании класса (не используется рефлексия), и обращается к нему именно по имени класса, а не интерфейса.
2. Я в курсе, что из разных. А что народ в тредах выше кипишит, что им придется зависимости одни и теже подтягивать, увелчивая расходы памяти
«Так вот почитал я статью от уважаемого XaocCPS, там получается, что код, который импортирует модуль (подключает к себе), уже знает о существовании класса (не используется рефлексия), и обращается к нему именно по имени класса, а не интерфейса.»
Это ошибка. MEF прекрасно грузит модули по интерфейсам и именам. Вы с typecatalog не путаете?
Пишем модульное приложение на .Net Framework