1

使用依赖注入容器时,在执行解析时检测到缺少依赖关系。这是在运行时。使用依赖注入容器时静态确定缺失的依赖关系

本文介绍部分解决方案。这将有助于简化测试,调试和维护,但它仍然需要测试执行,以验证您的行为(特别是如果你使用运行时分辨率抽象工厂子溶液):

http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

当使用依赖注入容器,有没有一种方法可以静态确定所有的依赖关系都将被解析?

回答

2

简答:不,不能完成。

这样做需要能够将所有组件及其依赖关系(容器元数据)表示为图形,以便对其进行分析。问题是,容器越复杂,它越难实现这一点。以温莎为例。它的numerous extension points使依赖关系过于动态,不能用图表来表示。懒惰的组件加载器,处理程序选择器,工厂,组件模型贡献者,子解析器都参与进程,它们可以是任意的用户代码,这使得不可能静态分析。

静态分析对于一个普通的容器来说可能是可行的,但是这个假设的容器对于真实世界的项目来说是相当无用的。

因此,像往常一样,这是一种折衷方案,我们能做的最好的一些测试是对容器中所有注册组件进行实际解析。 StructureMap有一个AssertConfigurationIsValid()方法来做到这一点。

即使如此,也可能会有更多细微的错误未被捕获,如lifestyle issues

+0

最佳实践对我来说绝对是有趣且有用的。我恰好在调查温莎,这对我来说尤其重要。感谢有用的链接:) – 2010-09-03 15:59:41

5

托管扩展性框架(MEF)可以执行此操作。为了使分析准确,您需要遵守一些最佳实践,但结果却不错。

要分析一组组件,使用命令行工具 - 请参见http://blogs.msdn.com/b/nblumhardt/archive/2009/08/28/analyze-mef-assemblies-from-the-command-line.aspx。这可以从Visual Studio或持续集成服务器中的构建脚本运行 - http://blogs.msdn.com/b/nblumhardt/archive/2009/09/24/debug-composition-from-within-visual-studio.aspx

您可以直观地做到这一点使用MefContrib项目的Visual MEFX(再次在一组组件) - 见http://xamlcoder.com/blog/2010/04/10/updated-visual-mefx/

MEF支持既是很声明(用于配置标准属性),并通过使用基本这个功能(它可以在不创建任何实例的情况下构建图表......)需要一点点围绕您的头部。)

+0

酷!从来没有想过这是可能的。然而,为了公平起见,它应该在Windsor中是可能的,因为它也将组件表示为图形节点,但仅限于容器的非常有限/静态的使用情况。 – 2010-09-04 23:19:18

+0

是的 - 它更多地涉及可以被分析而不是一个全有或全无的问题。 MEF进一步做出类似于Typed Factory Facility的分析。看看Krzysztof为Windsor v.3烹饪的内容会很有趣:) – 2010-09-05 11:47:43

1

除了Mauricio说的,Windsor 2.5还有一个功能,您可能会发现它有用诊断缺少依赖关系的问题或仅查看容器中的组件。

我写了一篇关于它的测试版here。它现在更加有用,并且和Windsor中的所有东西一样 - 它是可扩展的,因此您可以将自己的物品放在列表中。

alt text

0

也许不是一个依赖注入容器。但是,您可以手动执行依赖项注入,而无需使用容器。例如:

var foo = new Foo(); 
var bar = new Bar(foo); 
var program = new Program(bar); 
program.Run(); 

如果它编译,那么所有的依赖关系都在那里。但是,一旦依赖关系图增长得足够大,以至于无法将它完全保留在头部(特别是在混合中引发了一些循环依赖关系),麻烦就会一发不可收拾。如果重构涉及重新安排依赖关系,那么调整构造函数调用的顺序将变得很困难。

+0

虽然我很欣赏你的答案,但对我来说它并不是非常有用:)我希望我的团队的代码能够分离依赖关系的构建和对依赖关系的访问。 DI的这种使用使得它很容易忘记,或者无意中滑倒。这就是为什么我会主张使用DI容器和/或抽象工厂。 – 2010-09-27 22:47:07

+0

@Merlyn:我不太明白你的意思。手动依赖注入使构建阶段与其余代码保持完全相同的方式,与容器完全相同。上面的代码片段相当于'var program = container.Resolve ();'会做,并且会出现在代码中的相同位置。 – 2010-09-27 23:05:48

+0

对不起,我应该纠正自己。当我说访问时,我的意思是填充依赖性插槽。我使用这个作为测试隔离的解决方案,所以我可以注入mock。除非我抽象传递给代码的确切依赖关系,否则我会锁定调用代码传递的任何实现。我所知道的两种解决方案是抽象工厂类(这将允许我执行您在此描述的静态检查)和DI容器(这是我的问题所关注的)。我已经计划在两种情况下都使用构造函数注入。 – 2010-09-28 18:07:52