MEF,在请求分支时创建Import树

时间:2008-11-05 20:33:55

标签: c# .net mvp mef

使用MEF我想做以下事情。

我有一个WPF Shell。对于shell我想从另一个DLL导入一个UserControl,它也是我的MVP三元组的视图。 MVP三元组的工作方式是,在演示者中我有一个构造函数,它接受IModel和IView并将它们连接起来。 因此,为了实现这一点,我需要MEF来执行以下操作:

  1. 创建IView实施
  2. 创建IModel实施
  3. 创建Presenter并将IModel和IView传递给其构造函数
  4. 显示时将IView实施导入我的shell
  5. 相反它的作用是,它只创建Exporting IView类型并将其传递给shell,基本上跳过了第2步和第3步。当你想到它时,它非常合乎逻辑,但我怎么能告诉MEF也创建了当我要求IView时整个三合会。 我不需要在我的Shell中引用Presenter或模型。所以将它作为Import也不是一个选项(无论如何它都会非常丑陋:)。

    我正在使用最新的MEF(预览2刷新)。 任何人吗?

    ==更新==

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

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

2 个答案:

答案 0 :(得分: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被注入shell而不是View。如果Presenter正在创建View,那么您不能只是首先抓取View(就像他正在做的那样),否则将无法创建Presenter。嗯,你可以做到,但你最终会破解它。 Cleaner只是注入Presenter并让它暴露出IView。我们在Prism中做到了这一点并且效果很好。

答案 1 :(得分:1)

您在博文中概述的方式是使用MEF的完美有效方式。这是嵌套的组合,在设计时总是要记住Container是决策者,所以作为插件/扩展器供应商,你将专注于你“出口”的服务,作为一个重要的,你不应该不用担心你需要服务什么,或者“导入”(这一点在最后一滴中有一些问题,但我听到足够好以对它持乐观态度)。

因此,在嵌套组合中,您可能需要一些外部服务,但当时您也可以提供一些服务。当你做作曲时,它会将所有东西都插在一起。

我有一篇博客文章,其中包含两个说明这种思维方式的例子:

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

此外,要删除dll并观察其中的类型,您可以使用DirectoryPartCatalog来查看该文件夹。

您还需要注意同一合同有多个导出的方案,并根据提供的元数据确定正确的方案。