MEF,在请求分支时创建导入树

发布于 2024-07-08 23:09:34 字数 839 浏览 3 评论 0原文

使用 MEF 我想执行以下操作。

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

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

相反,它是做什么的?只创建 Exporting IView 类型并将其传递给 shell,基本上跳过了步骤 2 和 3。仔细想想,这很符合逻辑,但是当我请求 IView 时,如何告诉 MEF 也创建整个三元组。 我不需要在 Shell .dll 中的其他任何地方引用 Presenter 或模型,因此将其作为导入也不是一个选项(而且无论如何它都会非常难看:)。

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

==更新==

我找到了一个解决方案,并在此处发布了相关博客:
Krzysztof Koźmic 的博客 -使用 MEF 创建依赖关系树

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

Using MEF I want to do the following.

I have a WPF Shell. To the shell I want to Import from another DLL a UserControl that is also a View of my MVP triad.
The way the MVP triad works, is that in presenter I have a constructor that takes both IModel and IView and wires them up.
So, in order for this to work, I need MEF to do the following:

  1. Create IView implementation
  2. Create IModel implementation
  3. Create Presenter and pass IModel and IView to its constructor
  4. Import IView implementation into my shell when it gets displayed

Instead what it does, is it only creates the type Exporting IView and passes it to the shell, basically skipping steps 2 and 3. Its pretty logical, when you think about it, but how can I tell MEF to also create the whole triad when I ask for a IView.
I don't need to reference Presenter nor model anywhere else in my Shell .dll so puting it as an Import as well is not an option (and it would be quite ugly anyway :).

I'm using the latest drop of MEF (Preview 2 Refresh).
Anyone?

==Update==

I have found a solution and I blogged about it here:
Krzysztof Koźmic's blog - Creating tree of dependencies with MEF

However, I'd be more than happy if someone came up with a better solution.**

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹂绝世的画 2024-07-15 23:09:34

在这里检查我的答案。

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 中做到了这一点,效果非常好。

Check my answer here.

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

EDIT: (Added from the link, to prevent not being flagged as low quality / 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: }

So what’s going on here?

Shell gets injected with Presenter. Presenter gets injected with View and Model. Everything here is singletons, but doesn’t have to be.

The difference between our two examples is that the Presenter is getting injected into the shell rather than the View. If the Presenter is creating the View then you can’t just grab the View first (as he was doing), or the Presenter will not get created. Well you can do it, but you end up hacking it to bits. Cleaner is to just inject the Presenter and have it expose an IView. We did this in Prism and it worked quite well.

笔芯 2024-07-15 23:09:34

您在博客文章中概述的方式是利用 MEF 的完全有效的方式。 这是嵌套组合,在设计时最好记住容器是决定者,因此作为插件/扩展器供应商,您将专注于您正在“导出”的服务,并且作为重要的,您应该不用担心你需要维修什么,或者“导入”(这一点在最后一滴中有一些问题,但我听说足够好,对此持乐观态度)。

所以在嵌套组合中,你可能需要一些外部服务,但当时你也可以提供一些。 当您进行撰写时,它会将所有内容整合在一起。

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

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

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

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

The way you outlined in your blog post is the perfectly valid way for utilizing MEF. This is nested composition, and while designing it is always good to keep in mind that Container is the decider, so as a plug-in / extender vendor you will focus on your services that you are "exporting" and as an important, you shouldn't worry about what you need to be serviced, or "importing" (this point has some issues in the last drop, but I hear good enough to be optimistic about it).

So in nested composition, you may need some external services but at the time you can also be providing some. When you do a compose, it will plug everything together.

I have a blog post containing 2 examples illustrating this way of thinking :

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

Also, to drop the dll and watch the types in it, you can use DirectoryPartCatalog to watch that folder.

You will also need to watch out the scenarios where there are multiple exports for the same contract, and determine the right one from metadata provided.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文