我看了一下微软的托管可扩展性框架(MEF)和各种IoC容器(例如Unity),但我无法看出何时应该使用其中一种解决方案。具体来说,似乎MEF处理大多数IoC类型的模式,因此像Unity这样的IoC容器就不是很必要了。
理想情况下,我希望能看到一个很好的用例,说明在何种情况下IoC容器会被使用,而不是或者除了MEF之外。
我看了一下微软的托管可扩展性框架(MEF)和各种IoC容器(例如Unity),但我无法看出何时应该使用其中一种解决方案。具体来说,似乎MEF处理大多数IoC类型的模式,因此像Unity这样的IoC容器就不是很必要了。
理想情况下,我希望能看到一个很好的用例,说明在何种情况下IoC容器会被使用,而不是或者除了MEF之外。
简而言之,IoC容器通常适用于静态依赖关系(在编译时已知),而MEF通常适用于动态依赖关系(仅在运行时已知)。
因此,它们都是组合引擎,但每个模式的重点却非常不同。设计决策因此变化很大,因为MEF优化了未知部件的发现,而不是已知部件的注册。
这样想:如果您正在开发整个应用程序,则最好使用IoC容器。如果您正在编写可扩展性的代码,以便第三方开发人员将扩展您的系统,则MEF可能更适合。
此外,@Pavel Nikolov回答中的文章提供了一些很好的指导(由MEF的项目经理Glenn Block撰写)。
我已经使用MEF一段时间了,当我们的插件目录中有3-5个给定接口的实现时,我们使用它而不是IOC产品的关键因素在于,应该在运行时决定使用哪个实现。
MEF很擅长做到这一点。通常,IOC旨在确保您可以在将来的某个时间将基于ORM产品1的IUserRepository替换为基于ORM产品2的IUserRepository,但大多数IOC解决方案都假设在任何给定时间只会有一个IUserRepository处于有效状态。
然而,如果需要根据给定页面请求的输入数据来选择一个实现,则IOC容器通常无法胜任。
例如,我们对一个我已经工作了一段时间的大型Web应用程序进行权限检查和验证。使用MEF,我们可以查看记录的CreatedOn日期,并查找实际上在创建记录时生效的验证插件,然后将记录同时通过该插件和当前生效的验证器运行并比较记录的有效性随时间变化。
这种能力还使我们能够定义插件的回退覆盖。我正在处理的应用程序实际上是相同的代码库,部署了30多个实现。因此,我们通常通过请求以下内容来查找插件:
这使我们能够打包一组默认插件,只有在特定实现没有使用客户特定规则覆盖时才会启动。
IOC是一种伟大的技术,但似乎更多地是让编码接口而不是具体实现变得容易。然而,在IOC中交换这些实现更多是项目转型事件。在MEF中,您可以采取接口和具体实现的灵活性,并在许多可用选项之间做出运行时决策。
很抱歉偏离主题,我只是想说有两个缺陷使MEF成为一个不必要的复杂因素:
它是基于属性的,对于帮助您弄清楚为什么事情会发生并没有什么好处。无法获得埋在框架内部的详细信息,以查看确切的操作情况。无法获取跟踪日志或连接到解析机制,并手动处理未解决的情况。
它没有任何故障排除机制,无法查找某些部分被拒绝的原因。尽管指向了一个失败的部分,但它并没有告诉您该部分失败的原因。
所以我非常失望。我花费了太多时间在试图引导一些类而不是解决真正的问题上。我相信,当您完全控制创建什么、何时创建以及可以在VS调试器中跟踪任何内容时,没有比老派的依赖注入技术更好的选择。我希望支持MEF的人能提出一堆充分的理由,告诉我为什么我应该选择它而不是普通的依赖注入。
我同意MEF可以成为一个完全有能力的IoC框架。事实上,我正在编写一个基于使用MEF进行可扩展性和IoC的应用程序。我取出了它的通用部分,并将其制作成一个“框架”,并开源它作为自己的框架SoapBox Core,以便人们想要了解它的工作原理。
特别是,如果你想看看MEF的实际效果,请查看Host的工作原理。