MEF与任何IoC的比较

71

我看了一下微软的托管可扩展性框架(MEF)和各种IoC容器(例如Unity),但我无法看出何时应该使用其中一种解决方案。具体来说,似乎MEF处理大多数IoC类型的模式,因此像Unity这样的IoC容器就不是很必要了。

理想情况下,我希望能看到一个很好的用例,说明在何种情况下IoC容器会被使用,而不是或者除了MEF之外。


相关问题请参见此处 - Benjol
4个回答

77

简而言之,IoC容器通常适用于静态依赖关系(在编译时已知),而MEF通常适用于动态依赖关系(仅在运行时已知)。

因此,它们都是组合引擎,但每个模式的重点却非常不同。设计决策因此变化很大,因为MEF优化了未知部件的发现,而不是已知部件的注册。

这样想:如果您正在开发整个应用程序,则最好使用IoC容器。如果您正在编写可扩展性的代码,以便第三方开发人员将扩展您的系统,则MEF可能更适合。

此外,@Pavel Nikolov回答中的文章提供了一些很好的指导(由MEF的项目经理Glenn Block撰写)。


2
这篇MSDN文章真正让我明白了:http://msdn.microsoft.com/en-us/library/hh708870.aspx。对于一个熟悉IoC/ID的MEF新手来说,MEF似乎是注入(组合)...没有类型注册。因此,上面的SO答案真正让我明白了。现在正在听备受推崇的Hanselman播客中关于这个主题的内容:http://www.hanselminutes.com/148/mef-managed-extensibility-framework-with-glenn-block - NovaJoe
请指出一些具体的例子,其中任何IoC在静态依赖项(在编译时已知)方面比MEF更有用。我发现Export \ Import属性或Registration Builder对于静态依赖关系比复杂且容易出错的配置文件更有用。 - Aaron Stainback
1
@AaronStainback:我的首选容器是Autofac,它更喜欢基于代码的注册而不是配置文件,类似于Registration Builder(我不喜欢XML)。Autofac相对于MEF的优势包括:通过lambda表达式进行注册、细粒度的生命周期控制以及组合无知(组合类型不需要知道Autofac或它们所使用的上下文)。这些方面在您控制组合类型时最有优势,因此Autofac和MEF之间的重点差异。两者之间的Venn图通常涵盖更简单的DI场景。 - Bryan Watts
@AaronStainback:此外,请将踩票保留给不正确或误导性的答案,而不是反映个人偏好。缺少点赞已经传达了这一点。 - Bryan Watts
@BryanWatts:这个踩票不是因为个人喜好,而是因为你的回答过于主观,没有提供任何事实。你在回复中指出的项目本来就是很好的知识点,尽管它们并不完全准确。.NET 4.5中的MEF 2.0具有组合无知,因此我不认为这是一个优势。此外,MEF也可以通过lambda表达式进行注册,所以这一点也是平局。在.NET 4.5中,MEF还增加了更细粒度的生命周期管理。Autofac具有更多内置的生命周期策略,但MEF提供了构建它们的工具。 - Aaron Stainback

27

我已经使用MEF一段时间了,当我们的插件目录中有3-5个给定接口的实现时,我们使用它而不是IOC产品的关键因素在于,应该在运行时决定使用哪个实现。

MEF很擅长做到这一点。通常,IOC旨在确保您可以在将来的某个时间将基于ORM产品1的IUserRepository替换为基于ORM产品2的IUserRepository,但大多数IOC解决方案都假设在任何给定时间只会有一个IUserRepository处于有效状态。

然而,如果需要根据给定页面请求的输入数据来选择一个实现,则IOC容器通常无法胜任。

例如,我们对一个我已经工作了一段时间的大型Web应用程序进行权限检查和验证。使用MEF,我们可以查看记录的CreatedOn日期,并查找实际上在创建记录时生效的验证插件,然后将记录同时通过该插件和当前生效的验证器运行并比较记录的有效性随时间变化。

这种能力还使我们能够定义插件的回退覆盖。我正在处理的应用程序实际上是相同的代码库,部署了30多个实现。因此,我们通常通过请求以下内容来查找插件:

  1. 特定于当前站点和特定记录类型的接口实现。
  2. 特定于当前站点但适用于任何记录类型的接口实现。
  3. 适用于任何站点和任何记录的接口。

这使我们能够打包一组默认插件,只有在特定实现没有使用客户特定规则覆盖时才会启动。

IOC是一种伟大的技术,但似乎更多地是让编码接口而不是具体实现变得容易。然而,在IOC中交换这些实现更多是项目转型事件。在MEF中,您可以采取接口和具体实现的灵活性,并在许多可用选项之间做出运行时决策。


我喜欢通过MEF应用多个验证的示例。 - David Keaveny

5

很抱歉偏离主题,我只是想说有两个缺陷使MEF成为一个不必要的复杂因素:

  • 它是基于属性的,对于帮助您弄清楚为什么事情会发生并没有什么好处。无法获得埋在框架内部的详细信息,以查看确切的操作情况。无法获取跟踪日志或连接到解析机制,并手动处理未解决的情况。

  • 它没有任何故障排除机制,无法查找某些部分被拒绝的原因。尽管指向了一个失败的部分,但它并没有告诉您该部分失败的原因。

所以我非常失望。我花费了太多时间在试图引导一些类而不是解决真正的问题上。我相信,当您完全控制创建什么、何时创建以及可以在VS调试器中跟踪任何内容时,没有比老派的依赖注入技术更好的选择。我希望支持MEF的人能提出一堆充分的理由,告诉我为什么我应该选择它而不是普通的依赖注入。


1

我同意MEF可以成为一个完全有能力的IoC框架。事实上,我正在编写一个基于使用MEF进行可扩展性和IoC的应用程序。我取出了它的通用部分,并将其制作成一个“框架”,并开源它作为自己的框架SoapBox Core,以便人们想要了解它的工作原理。

特别是,如果你想看看MEF的实际效果,请查看Host的工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接