最近使用了其中的 6 个(Windsor、Unity、Spring.Net、Autofac、Ninject、StructureMap)我可以快速总结每一个,我们的选择标准和我们最终的选择。
注意:我们没有将 PicoContainer.Net 视为我们的团队之一,他们认为 .Net 端口与 Java 版本相比相当差。我们也没有关注 ObjectBuilder,因为 Unity 是在 ObjectBuilder2 之上构建的,默认情况下被认为是更好的选择。
首先,我可以说它们或多或少都非常相似,这实际上归结为最适合您的方法以及您的具体要求。我们的要求包括:
要求
测试
每个容器都用于一个典型的 Asp.Net webforms 项目(因为这是我们的目标应用程序类型)。我们使用带有单个简单用户控件的单个简单页面,每个控件分别继承自一个基本页面/基本控件。我们在BasePage 上使用 1 个容器作为“per request”范围容器,在 global.asax 上使用 1 个容器作为“应用程序”范围,并尝试将它们链接在一起,以便可以从两个容器中解决依赖关系。
每个 Web 应用程序共享一组人为的域对象,模拟多层次的依赖关系、范围类型(单例/瞬态)以及托管和非托管类(需要IDisposable)。 “顶级”依赖组件是从 BasePage 上的方法手动注入的。
结果
Windsor - 满足所有标准并拥有良好的案例历史、博客社区和在线文档。易于使用,可能是事实上的选择。通过工厂设施创建高级组件。还允许链接单独创建的容器。
Spring.Net - 冗长且无用的文档以及不明显/易于可编程配置。不支持泛型。未选择
Ninject - 易于使用,文档清晰。强大的功能集可以满足我们的所有要求,但容器层次结构除外,因此很遗憾没有被选中。
StructureMap - 文档很少,虽然有一个非常高级的功能集可以满足我们的所有要求,但是没有用于容器层次结构的内置机制,尽管可以使用 for 循环一起破解参见 here lambda 表达式流式接口起初看起来确实有点过于复杂,但可以封装起来。
Unity - 有据可查、易于使用并符合我们所有的选择标准,并且有一个简单的扩展机制来添加我们需要的创建前/后创建事件机制。必须从父容器创建子容器。
Autofac - 有据可查且相对易于使用,虽然 lambda 表达式配置看起来确实有点过于复杂,但同样可以轻松封装。组件范围是通过“标记”机制实现的,并且所有组件都使用构建器预先配置,这有点不方便。子容器是从父容器创建的,并从“标签”分配组件。允许泛型注入。
结论
我们最终的选择是在 Windsor 和 Unity 之间,而这一次我们选择了 Unity,因为它易于使用、文档、扩展系统以及处于“生产”状态。