哪个依赖注入工具应该使用?

39

相关问题 https://dev59.com/N3E95IYBdhLWcg3wp_og - Quintin Par
ObjectBuilder不是一个DI框架。它是一个用于构建DI框架的框架。 - Steven
9个回答

61

最近我们使用了6个这些框架 (Windsor, Unity, Spring.Net, Autofac, Ninject, StructureMap),我可以简单介绍一下每个框架、我们的选择标准和最终选择。

注意:我们没有考虑PicoContainer.Net,因为我们团队中的一名成员认为它的 .Net 版本与 Java 版本相比非常差。我们也没有考虑 ObjectBuilder,因为 Unity 是基于 ObjectBuilder2 构建的,因此默认被认为是更优秀的选择。

首先,我可以说几乎所有框架都非常相似,它们的区别实际上在于哪个最适合您和您的具体要求。我们的要求包括:

要求

  • 基于构造函数的注入(我们打算使用属性、字段或方法注入)
  • 可编程配置(使用 XML)
  • 容器层次结构(每个应用程序、每个请求和每个会话一个容器,以更隐式地将组件生命周期范围绑定到容器)
  • 组件生命周期管理(用于更精细的作用域,例如瞬态 / 单例)
  • 从接口到类型或具体实例的注入(例如 ILogger -> typeof(FileLogger)ILogger -> new FileLogger()
  • 高级组件创建 / "创建事件机制" 用于预/后初始化
  • IDisposable 组件在容器拆除时正确处理
  • 文档完整易懂且可轻松获得在线信息

    注意:尽管性能是一项要求,但在选择过程中并未考虑它,因为根据这个基准测试,所有被审查的容器似乎都很相似。

测试

每个容器都在一个典型的Asp.Net WebForms项目中使用(因为这是我们的目标应用程序类型)。我们使用了一个简单的页面和一个简单的用户控件,每个都从一个基本页面/基本控件继承。我们在BasePage上使用1个“按请求”范围容器和1个全局.asax上的“应用程序”范围,试图将它们链接在一起,以便可以从两个容器中解析依赖项。

每个Web应用程序共享一组虚构的域对象,模拟多级依赖、作用域类型(单例/瞬态)以及托管和非托管类(需要IDisposable)。 “顶层”依赖组件是从BasePage的方法手动注入的。

结果

Windsor - 满足所有标准,具有良好的案例历史记录、博客社区和在线文档。易于使用,可能是默认选择。通过工厂设施进行高级组件创建。也允许链接单独创建的容器。

Spring.Net - 冗长且不可靠的文档,没有明显/易于编程配置。不支持泛型。未被选中。

Ninject - 易于使用,具有清晰易懂的文档。功能强大,满足我们所有需求,除了容器层次结构,因此遗憾地未被选择。

StructureMap - 文档质量较差,尽管具有相当先进的功能集,满足我们所有的要求,但没有内置的容器层次结构机制,虽然可以使用for循环来拼凑,参见这里。Lambda表达式流畅接口一开始似乎有点过于复杂,但可以封装起来。

Unity - 非常好的文档,易于使用,并满足我们所有的选择标准。它具有易于扩展的机制,可以添加我们所需的前/后创建事件机制。必须从父容器创建子容器。

Autofac - 很好的文档,相对易于使用,尽管lambda表达式配置似乎有点复杂,但也可以轻松地封装起来。组件作用域通过“标记”机制实现,并且所有组件都是在构建器中预先配置的,这有点不方便。子容器从父容器创建,并从“标记”中分配组件。允许泛型注入。

结论

我们最终的选择是Windsor和Unity之间,这一次我们选择了Unity,因为它易于使用、文档齐全、扩展系统完备并处于“生产”状态。


聪明而合理的推理。 - Sandor Davidhazi
15
有趣的是,被接受的答案说要避免使用Unity,而得票最高的答案选择了Unity! - Abdu
2
是的,我也觉得那很有趣。我们给了所有容器相同的重视,忽略了反Microsoft的偏见。然而,每种情况都不同,人们应该选择适合他们的解决方案。恰好我们最终重新发明了轮子,并编写了自己的代码,我们很快会开源。 - Xian
这是一个有点“厚颜无耻”的宣传,但基于我的研究,我已经为.Net创建了一个轻量级容器。我相信它目前是行业中最快的,并且封装了我在IoC中最需要的东西。但请注意:这还是一个正在进行中的工作 http://code.google.com/p/yadic/ - Xian
这个答案怎么了?它的最后一部分好像丢失了... - M4N
由于这个错误:http://meta.stackexchange.com/questions/14097/answer-to-question-cut-in-the-middle-in-question-view-in-full-in-edit-view-clos,我编辑了问题,以便完整显示。 - M4N

12

如果您的系统考虑了IoC/DI,坚持使用一个容器并不是非常重要的。通过正确的方法,您可以轻松更改道路上的IoC库。

当然,容器必须提供足够的灵活性来支持常见的广泛使用的场景(生命周期管理、适当的容器嵌套、XML和代码配置、拦截、快速解析)。

我建议在Castle(广泛使用且有很多集成库)和Autofac(轻量级、快速且具有适当的容器嵌套,但不是那么广泛使用)之间进行选择。

Hanselman提供了一份详尽的IoC容器列表

PS:您不想使用Unity


14
你能详细说明一下Unity的评论吗?为什么它是一个不好的选择? - vitule
在使用企业库之后,无论微软尝试创建任何类似于“策略注入器”的东西,我都有非常负面和过敏的反应!!除了ASP.NET MVC :) - user156888
仅仅告诉别人不要使用某个东西,而没有任何评论或信息来说服他们,这并不是一个好的方法(10年后的评论 :))。 - Mohammed Noureldin

12

哇,这篇文章详细程度惊人。完全值得一读。它还有第二部分:http://blog.ashmind.com/index.php/2008/09/08/comparing-net-di-ioc-frameworks-part-2/ - Joe White

5

一年前我开始使用Autofac,从此再也没有回头。


4

我是Autofac的粉丝,但Windsor和Unity也可以胜任(尽管Windsor比Unity更强大,而且不需要为您的代码添加属性)。然而,在一个系统中坚持使用单个容器有很多好的非技术原因。


2
你为什么认为Unity要求你归属你的代码?我正在使用它,根本不需要归属我的代码。 - Anthony

2

1
MEF 不是一个 IoC 容器:https://dev59.com/BHVD5IYBdhLWcg3wO5ID#98848 - Mauricio Scheffer
2
@Mauricio Scheffer:MEF在解决许多架构问题时使用依赖注入模式,这些问题是人们开始考虑将IOC / DI框架引入项目时面临的。OP没有提供任何迹象表明他的需求超出了MEF擅长的范围,在这种情况下,它可能是一种简单,可行且极其轻量级的选择。 - Sam Harwell

2

使用适合你的工具。大多数工具都有独特的功能,几乎所有工具都比Unity更加丰富。如果Unity是你所需要的全部,那么你当然可以使用它。

仅仅因为Microsoft的Unity来自于微软而使用它是做决策的一种不好的方式。思考你需要什么和为什么需要,选择适合你需求的工具。

然而,如果可能的话,坚持使用单一容器也是一个好主意。


0

IoC容器基准测试-性能比较提供了20多个产品的性能和功能比较表,并保持最新状态。

文章的结论:

SimpleInjector、Hiro、Funq、Munq和Dynamo提供了最佳性能,它们非常快。试试它们吧!

特别是Simple Injector似乎是一个不错的选择。它非常快,有很好的文档,还支持像拦截和通用装饰器这样的高级场景。


0

除非您已经有使用其中一种可能的IoC容器解决方案所使用的特定子技术的经验和个人偏好,否则它们都能很好地发挥作用,我没有看到任何一个具有“杀手级功能”的特别突出。Unity可能是最适合已经使用P&P Enterprise Library 4.x的解决方案...


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