Какая структура управляемой расширяемости для .NET?

Кто-нибудь много работал с Microsoft Managed Extensibility Framework (MEF)? Kinda звучит так, будто он пытается быть всем для всех людей - это менеджер надстройки! Это утка, набирая! Мне интересно, есть ли у кого-нибудь опыт, положительный или отрицательный.

В настоящее время мы планируем использовать общую реализацию IoC ala MvcContrib для нашего следующего крупного проекта. Должны ли мы выбросить MEF в микс?

Ответ 1

Мы не стремимся к тому, чтобы MEF был универсальным IoC. Лучший способ подумать о аспектах IoC MEF - это детализация реализации. Мы используем IoC в качестве шаблона, потому что это отличный способ решить проблемы, которые мы планируем решить.

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

Представьте, когда вы хотите расширить нашу платформу в будущем, вы удалите dll в папку bin, и все готово. Приложение с поддержкой MEF загорается с новым расширением. Это видение MEF.

Ответ 2

Это сообщение относится к предварительному просмотру Framework 2.

Итак, я прошел через MEF и написал быстрый "Hello World", который представлен ниже. Я должен сказать, что было легко погрузиться и понять. Система каталогов великолепна и делает расширение MEF очень простым. Это тривиально, чтобы указать его в каталог сборок addin и позволить ему обрабатывать остальные. Наследие MEF ala Prism, безусловно, демонстрируется, но я думаю, что это было бы странно, если бы это не так, учитывая, что обе структуры связаны с композицией.

Я думаю, что вещь, которая больше всего наклеивается на мой craw, - это "волшебство" _container.Compose(). Если вы посмотрите на класс HelloMEF, вы увидите, что поле приветствия никогда не инициализируется никаким кодом, что просто смешно. Я думаю, что предпочитаю, как работают контейнеры IoC, где явным образом прошу контейнер создать объект для вас. Интересно, может ли быть какой-то "ничто" или "пустой" общий инициализатор. то есть.

private IGreetings greetings = CompositionServices.Empty<IGreetings>();

Это по крайней мере заполняет объект "чем-то" до тех пор, пока код компоновки контейнера не запустится, чтобы заполнить его реальным "чем-то". Я не знаю - это немного смахивает на ключевые слова Visual Basic Empty или Nothing, которые мне всегда не нравились. Если у кого-нибудь есть какие-то мысли по этому поводу, я бы хотел их услышать. Может быть, это то, что мне просто нужно преодолеть. Он отмечен большим жирным атрибутом [Import], поэтому ему не нравится полная тайна или что-то еще.

Управление временем жизни объекта не является очевидным, но все по умолчанию является одиночным, если вы не добавили атрибут [CompositionOptions] к экспортированному классу. Это позволит вам указать либо Factory, либо Singleton. Было бы неплохо увидеть, что Pooled добавлен в этот список в какой-то момент.

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

Я думаю, было бы неплохо затенять копию DLL, загружаемых каталогом DirectoryPartCatalog. Прямо сейчас библиотеки DLL блокируются, как только MEF их удерживает. Это также позволит вам добавить наблюдателя в каталог и уловить обновленные дополнения. Это было бы очень мило...

Наконец, я беспокоюсь о том, насколько надежны DLL файлы addin и как, или если MEF будет вести себя в частичной среде доверия. Я подозреваю, что приложения, использующие MEF, потребуют полного доверия. Также может быть разумным загрузить дополнительные элементы в свой собственный AppDomain. Я знаю, что это немного портит System.AddIn, но это позволит очень четкое разделение между пользовательскими добавлениями и системными добавлениями.

Хорошо - достаточно болтаться. Здесь Hello World в MEF и С#. Наслаждайтесь!

using System;
using System.ComponentModel.Composition;
using System.Reflection;

namespace HelloMEF
{
    public interface IGreetings
    {
        void Hello();
    }

    [Export(typeof(IGreetings))]
    public class Greetings : IGreetings
    {
        public void Hello()
        {
            Console.WriteLine("Hello world!");
        }
    }

    class HelloMEF : IDisposable
    {
        private readonly CompositionContainer _container;

        [Import(typeof(IGreetings))]
        private IGreetings greetings = null;

        public HelloMEF()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);
            var batch = new CompositionBatch();
            batch.AddPart(this);
            container.Compose(batch);

        }

        public void Run()
        {
            greetings.Hello();
        }

        public void Dispose()
        {
            _container.Dispose();
        }

        static void Main()
        {
            using (var helloMef = new HelloMEF())
                helloMef.Run();
        }
    }
}

Ответ 3

На вопрос Энди о безопасности для расширений, которые загружаются MEF (извините, у меня пока нет достаточного количества очков:)), место для обращения это находится в Каталоге. Каталоги MEF полностью подключаются, поэтому перед загрузкой вы можете написать собственный каталог, который проверяет ключи сборки и т.д. Вы могли бы даже использовать CAS, если хотите. Мы смотрим, возможно, с помощью крючков, чтобы вы могли сделать это без необходимости писать каталог. Однако источник для текущих каталогов свободно доступен. Я подозреваю, что минимум - это кто-то (может быть, в нашей команде) будет реализовывать его и бросить его в проекте расширения/вклада на CodePlex.

Ответ 4

Утиная печать не будет отправляться в V1, хотя она находится в текущем падении. В будущем случае мы заменим его на переходный механизм, в котором можно зацепить механизм печати утиной. Причина, по которой мы смотрели на утиную печать, - это обращение к сценариям версий. С Duck Typing вы можете удалить общие ссылки между экспортерами и импортерами, тем самым позволяя нескольким версиям контракта жить бок о бок.

Ответ 5

Энди, я считаю, что Glenn Block отвечает на многие из таких естественных вопросов, как эти в этой теме на форуме MSDN MEF:

Сравнение составаContainer с традиционными контейнерами IoC.

В какой-то степени ответ Артема выше правилен относительно первичного замысла MEF, который является расширяемостью, а не композицией. Если вы в первую очередь заинтересованы в композиции, используйте один из других обычных подозреваемых IoC. Если, с другой стороны, вы, в первую очередь, заинтересованы в расширяемости, то введение каталогов, частей, тегов метаданных, утиная печать и отложенная загрузка все делают для некоторых интересных возможностей. Кроме того, Krzysztof Cwalina делает снимок здесь при объяснении того, как MEF и System.Addins связаны друг с другом.

Ответ 7

Это не инъекция контрольного контейнера. Это плагин поддержки поддержки.

Ответ 8

Я бы сказал, что, учитывая, что он собирается отвиснуть от пространства имен System в платформе .NET 4.0, вы не ошибетесь. Будет интересно посмотреть, как развивается MEF и какое влияние оказывает Hamilton Verissimo (Castle) на направление MEF.

Если он ошеломляет как утку, это может быть частью текущей стаи контейнеров IoC...