MEF, создание дерева импорта при запросе ветки - PullRequest
1 голос
/ 05 ноября 2008

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

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

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

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

Я использую последнюю каплю MEF (Preview 2 Refresh). Кто-нибудь?

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

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

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

Ответы [ 2 ]

2 голосов
/ 13 ноября 2008

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

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. Если Presenter создает представление, то вы не можете просто сначала захватить представление (как он это делал), иначе Presenter не будет создан. Ну, вы можете сделать это, но вы в конечном итоге взломать его на куски. Очиститель - это просто ввести Presenter и выставить IView. Мы сделали это в Prism, и это сработало довольно хорошо.

1 голос
/ 13 ноября 2008

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...