【问题标题】:MEF = may experience frustration?MEF = 可能会感到沮丧?
【发布时间】:2010-04-16 18:11:03
【问题描述】:

更新

当我试图让 MEF 在我的整个应用程序中工作时,我遇到了更多的地方,我只是不明白为什么它没有在我期望的时候自动创建我的库。我认为这一切都回到了 Reed 所说的需要 MEF 来创造一切。所以现在,我有一个需要使用我的 CandySettings 的 XML 阅读器类,但即使它的 ICandySettings 属性具有 [Import] 属性,它也不会被导入。首先我发现 [Import] 不适用于静态,所以我改变了这个。但在那之后它仍然没有工作。我认为这是因为我手动创建了 XML 阅读器对象,而 MEF 想要我做的是 [Import] XML 阅读器......这意味着我现在也必须有一个接口。

这几乎就像使用 IoC(或至少对于 MEF)一样,是全有或全无的事情。你不能随意地到处使用它,因为最终你想要注入属性的任何类也需要由 MEF 创建。

如有错误请指正!


原帖

嗯,还没有那么糟糕。 :) 但是在 Reed 向我指出 MEF 作为 IoC 的潜在替代品之后,我确实有疑问(到目前为止它看起来确实不错)。

考虑以下模型: alt text http://bit.ly/9W0sHt

如您所见,我有一个应用程序,该应用程序使用插件(哎呀,错过了那个关联!)。应用程序和插件都需要使用 CandySettings 类型的对象,该对象可在另一个程序集中找到。

我第一次尝试在 MEF 中使用 ComposeParts 方法,但我可以让它工作的唯一方法是在 plugin 代码中执行类似的操作。

var container = new CompositionContainer();
container.ComposeParts(this, new CandySettings());

但这没有任何意义,因为我为什么要在插件中创建 CandySettings 的实例?它应该在应用程序中。但是如果我把它放在 App 代码中,那么即使我在插件中使用 [Import],在 CandySettings 中使用 [Export],插件也不会神奇地弄清楚如何访问 ICandySettings。 EDIT(可能是因为我应该从 App 调用 ComposeParts() 然后将其传递给插件?)

我这样做的方法是使用 MEF 的 DirectoryCatalog,因为这允许插件在构建时扫描当前文件夹中的所有程序集并自动导入所有标有 [导入]属性。所以它看起来像这样,并且可能在 every 插件中:

var catalog = new DirectoryCatalog(".");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

这完全有效,但我不禁认为这不是 MEF 的预期用途?

【问题讨论】:

  • 我记得使用 MEF 存在一些实际限制,并且它的预期用途是用于 Visual Studio 等应用程序,因此您应该首先确保您的设计符合他们的假设。基本上说这“不适合所有人”。 codebetter.com/blogs/glenn.block/archive/2009/08/16/…
  • 我认为它会成功,但这是我现在成为 .NET 程序员所期望的事情之一。给猫剥皮的方法有很多,基本上你能弄明白的唯一方法就是尝试几种方法。到目前为止,我已经在 MEF 和 Unity 中实现了我的代码,并且两者都可以工作,尽管我仍然不确定我在这两个框架中的实现方式是否 100% 正确。
  • 您能否添加您从ComposeParts 获得的错误消息、您用于初始化容器的代码以及您用于导出/导入的代码?
  • @Daniel:好的,我再次修改了我的问题。感谢您的关注!
  • 听起来您有两种标记为[Export(typeof(IError))]。如果是这样,则组合不知道在构建插件时使用哪一个。您应该开始针对新问题提出新问题,以便正确关联答案。这个太长了,对新人有用。

标签: c# dependency-injection inversion-of-control ioc-container mef


【解决方案1】:

这里的“诀窍”是您想让 MEF 为您创建插件。

这样做的方式是让您的应用程序自行编写,并指定插件类型:

class PluginRepository
{
    [ImportMany(typeof(IPlugin))]
    IEnumerable<IPlugin> Plugins { get; set; }
}

如果您这样做,并让 MEF 编写您的“存储库”类,MEF 将构建对象。然后它会在构造它们时自动组合它们,因此ICandySettings 将在无需您干预的情况下组合。

如果 MEF 没有为您构建对象,您只需要手动“组合”它。

【讨论】:

  • 好的,我试试,谢谢!如果这在测试应用程序中有效,那么在真正的应用程序中可能的最终结果是用你的代码替换我的插件加载器(当前使用反射的那个),对吧?
  • @Dave:是的。你根本不需要使用反射。 MEF 使这变得非常简单,非常可靠,并且代码非常短......
  • @Reed:好的,所以我有我的 App [Import] 我的插件界面。我的应用程序还使用 DirectoryCatalog 来查找所有程序集的导入。我的插件 [Import] 的 ICandySettings 和我的 CandySettings 库通过 [Export(typeof(ICandySettings))] 属性导出。我单步执行了代码,并在 App 中确认 CandySettings 对象和 Plugin 对象已被实例化。但是插件的构造函数需要 CandySettings,并且在构造点 CandySettings 没有得到解决......这是一个限制还是你认为我连接错了什么?我得到一个空异常。
  • @Reed:只是为了好玩,我继续使用 CandySettings 直到插件构建之后,现在它可以工作了!所以我猜MEF和Unity有同样的限制,你不能指望属性依赖被注入到构造函数中。我可能应该考虑将其更改为构造函数注入,我想?
  • @Dave:是的。使用 MEF,您可以让构造函数使用 [ImportingConstructor] 并将 ICandySettings 作为参数。这使得 MEF 首先构造 CandySettings,然后将其传递给您的构造函数。
猜你喜欢
  • 2016-07-07
  • 2018-04-27
  • 2011-05-29
  • 2011-01-26
  • 1970-01-01
  • 2014-07-21
  • 2013-06-06
  • 1970-01-01
相关资源
最近更新 更多