MEF, создание дерева импорта при запросе ветки

Используя MEF, я хочу сделать следующее.

У меня есть оболочка WPF. В оболочку я хочу импортировать из другой DLL пользовательский элемент управления, который также является представлением моей триады MVP. Триада MVP работает следующим образом: в Presenter у меня есть конструктор, который берет и IModel, и IView и связывает их. Итак, чтобы это работало, мне нужно, чтобы MEF сделал следующее:

  1. Создать реализацию IView
  2. Создать реализацию IModel
  3. Создайте Presenter и передайте IModel и IView его конструктору.
  4. Импортировать реализацию IView в мою оболочку, когда она отображается

Вместо этого он только создает тип Exporting IView и передает его в оболочку, в основном пропуская шаги 2 и 3. Это довольно логично, если подумать, но как я могу сказать MEF также создать всю триаду, когда Я прошу IView. Мне не нужно ссылаться ни на Presenter, ни на модель где-либо еще в моей оболочке .dll, поэтому помещать его в качестве импорта также не вариант (и в любом случае это было бы довольно уродливо :).

Я использую последнюю версию MEF (Preview 2 Refresh). Любой?

==Обновление==

Я нашел решение и написал об этом в своем блоге здесь:
Блог Кшиштофа Козмича - Создание дерева зависимостей с помощью MEF

Однако я был бы более чем счастлив, если бы кто-то предложил лучшее решение.**


.net c# mvp mef
person Krzysztof Kozmic    schedule 05.11.2008    source источник
comment
Вы поместили [ImportingConstructor] в конструктор?   -  person Glenn Block    schedule 07.11.2008
comment
Да, я сделал, проверьте ссылку, которую я предоставил, там есть упрощенная версия кода и мое решение. Это работает, но мне интересно, есть ли лучший способ сделать это.   -  person Krzysztof Kozmic    schedule 07.11.2008


Ответы (2)


Проверьте мой ответ здесь.

http://codebetter.com/blogs/glenn.block/archive/2008/11/12/mvp-with-mef.aspx

РЕДАКТИРОВАТЬ: (Добавлено по ссылке, чтобы не быть помеченным как низкое качество/LOA)

   1: using System.ComponentModel.Composition;
   2: using System.Reflection;
   3: using Microsoft.VisualStudio.TestTools.UnitTesting;
   4:  
   5: namespace MVPwithMEF
   6: {
   7:     /// <summary>
   8:     /// Summary description for MVPTriadFixture
   9:     /// </summary>
  10:     [TestClass]
  11:     public class MVPTriadFixture
  12:     {
  13:         [TestMethod]
  14:         public void MVPTriadShouldBeProperlyBuilt()
  15:         {
  16:             var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
  17:             var container = new CompositionContainer(catalog.CreateResolver());
  18:             var shell = container.GetExportedObject<Shell>();
  19:             Assert.IsNotNull(shell);
  20:             Assert.IsNotNull(shell.Presenter);
  21:             Assert.IsNotNull(shell.Presenter.View);
  22:             Assert.IsNotNull(shell.Presenter.Model);
  23:         }
  24:     }
  25:  
  26:     [Export]
  27:     public class Shell
  28:     {
  29:         private IPresenter _presenter = null;
  30:         
  31:         public IPresenter Presenter
  32:         {
  33:             get { return _presenter; }
  34:         }
  35:  
  36:         [ImportingConstructor]
  37:         public Shell(IPresenter presenter)
  38:         {
  39:             _presenter = presenter;
  40:         }
  41:     }
  42:  
  43:     public interface IModel
  44:     {
  45:     }
  46:  
  47:     [Export(typeof(IModel))]
  48:     public class Model : IModel
  49:     {
  50:         
  51:     }
  52:  
  53:     public interface IView
  54:     {
  55:     }
  56:  
  57:     [Export(typeof(IView))]
  58:     public class View : IView
  59:     {
  60:     }
  61:  
  62:     public interface IPresenter
  63:     {
  64:         IView View { get;}
  65:         IModel Model { get; }
  66:     }
  67:  
  68:     [Export(typeof(IPresenter))]
  69:     public class Presenter : IPresenter
  70:     {
  71:  
  72:         private IView _view;
  73:         private IModel _model;
  74:  
  75:         [ImportingConstructor]
  76:         public Presenter(IView view, IModel model)
  77:         {
  78:             _view = view;
  79:             _model = model;
  80:         }
  81:  
  82:         public IView View
  83:         {
  84:             get { return _view; }
  85:         }
  86:  
  87:         public IModel Model
  88:         {
  89:             get { return _model; }
  90:         }
  91:  
  92:     }
  93: }

Так что же здесь происходит?

Shell внедряется с помощью Presenter. Presenter получает инъекцию View и Model. Здесь все синглтоны, но не обязательно.

Разница между нашими двумя примерами заключается в том, что Presenter внедряется в оболочку, а не View. Если Presenter создает View, то вы не можете просто сначала захватить View (как он это делал), иначе Presenter не будет создан. Ну, вы можете это сделать, но в конечном итоге вы взломаете его на куски. Cleaner заключается в том, чтобы просто внедрить Presenter и открыть IView. Мы сделали это в Prism, и это сработало довольно хорошо.

person Glenn Block    schedule 12.11.2008
comment
(+1), хотя это, кажется, отвечает на вопрос, это сообщение считается постом низкого качества, поскольку ответ - это просто ссылка. Гораздо лучше, если помимо ссылки в порядке было бы описание или краткое изложение проблемы и предложенное по ссылке решение. решил оставить здесь примечание, так как оно было помечено как низкое качество. - person Arun; 23.03.2013

То, как вы описали в своем сообщении в блоге, является совершенно правильным способом использования MEF. Это вложенная композиция, и при проектировании всегда полезно помнить, что Container является решающим фактором, поэтому, как поставщик подключаемого модуля/расширителя, вы сосредоточитесь на своих услугах, которые вы «экспортируете», и, что важно, вы должны не беспокойтесь о том, что вам нужно обслуживать или «импортировать» (в этом пункте есть некоторые проблемы в последней капле, но я слышал достаточно хорошо, чтобы быть оптимистичным).

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

У меня есть сообщение в блоге, содержащее 2 примера, иллюстрирующих этот образ мышления:

http://www.sidarok.com/web/blog/content/2008/09/26/what-is-this-managed-extensibility-framework-thing-all-about.html

Кроме того, чтобы удалить dll и просмотреть типы в ней, вы можете использовать DirectoryPartCatalog для просмотра этой папки.

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

person Community    schedule 12.11.2008