1

使用 MEF 我想做以下事情。

我有一个 WPF 外壳。我想从另一个 DLL 导入一个 UserControl 到 shell,它也是我的 MVP 三元组的一个视图。MVP 三元组的工作方式是,在演示者中,我有一个构造函数,它同时接受 IModel 和 IView 并将它们连接起来。因此,为了使其正常工作,我需要 MEF 执行以下操作:

  1. 创建 IView 实现
  2. 创建 IModel 实现
  3. 创建 Presenter 并将 IModel 和 IView 传递给它的构造函数
  4. 显示时将 IView 实现导入我的 shell

相反,它的作用是只创建类型 Exporting IView 并将其传递给 shell,基本上跳过步骤 2 和 3。当您考虑它时,它非常合乎逻辑,但是我如何告诉 MEF 也创建整个三元组我要一个IView。我不需要在我的 Shell .dll 中的其他任何地方引用 Presenter 或模型,因此将其作为 Import 也不是一种选择(无论如何它都会非常难看:)。

我正在使用最新的 MEF(Preview 2 Refresh)。任何人?

==更新==

我找到了一个解决方案,并在这里写了一篇博客:
Krzysztof Koźmic's blog - Creating tree of dependencies with MEF

但是,如果有人提出更好的解决方案,我会非常高兴。**

4

2 回答 2

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 被注入视图和模型。这里的一切都是单例,但不一定是。

我们两个示例之间的区别在于,Presenter 被注入到 shell 而不是 View 中。如果演示者正在创建视图,那么您不能只是先获取视图(就像他所做的那样),否则演示者将不会被创建。好吧,你可以做到,但你最终会把它砍成碎片。Cleaner 就是注入 Presenter 并让它暴露一个 IView。我们在 Prism 中做到了这一点,并且效果很好。

于 2008-11-12T23:08:57.373 回答
1

您在博文中概述的方式是使用 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 来查看该文件夹。

您还需要注意同一合约有多个导出的场景,并从提供的元数据中确定正确的导出。

于 2008-11-12T22:01:55.090 回答