仅在应用程序启动时使用DI容器?

通常,我将在c#中使用dependency injection容器(unity),如下例所示:

class SomeClass { private readonly ILogger _logger; public SomeClass() { _logger = DependencyContainer.Resolve(); } public void DoSomething() { var someOtherClass = DependencyContainer.Resolve(); someOtherClass().whatElseEver(); } } 

昨天,我已经阅读了一些关于使用di容器进行正确dependency injection的文章。 在此之后,我知道我的例子非常糟糕。 这不是dependency injection,这就像服务定位器。

好的,怎么解决这个? 我认为使用构造函数注入可以轻松解决此问题:

 class SomeClass { private readonly ILogger _logger; private readonly ISomeOtherClass _someOtherClass; public SomeClass(ILogger logger, ISomeOtherClass someOtherClass) { _logger = logger; _someOtherClass = someOtherClass; } public void DoSomething() { _someOtherClass().whatElseEver(); } } 

现在我已经正确实现了dependency injection原则。 但是如何连接所有这些依赖项呢? 我有一个调用者类,它解决了“SomeClass”类所需的所有重要性:

 class SomeClassCaller { public void DoSomething() { var logger = DependencyContainer.Resolve(); var someOtherClass = DependencyContainer.Resolve(); var someClass = new SomeClass(logger, someOtherClass); someClass.DoSomething(); } } 

但是这个例子仍然使用依赖容器作为服务定位器,这很糟糕。 在几乎所有关于此的文章中,我都读过,只应该在应用程序的根/入口点使用依赖容器,这是正确的吗?

这意味着,没有类应该具有动态解决与“服务定位器”的一些依赖关系的能力,如记录器。 我要通过构造函数将ILogger注入到几乎每个类中,以避免这个问题,对吗? 这种方式感觉非常糟糕,如果我将ILogger通过10个类进入每个构造函数,不是吗?

所以,如果我有一个复杂的依赖图,我只能使用依赖容器?

有人可以给我一个例子,如果你使用依赖容器,只在应用程序的根目录?

如果SomeClassCaller需要SomeClass ,请将其注入:

 public class SomeClassCaller { private readonly SomeClass someClass; public SomeClassCaller(SomeClass someClass) { this.someClass = someClass; } public void DoSomething() { this.someClass.DoSomething(); } } 

这是具体依赖关系的一个例子。 通常,您可以让SomeClass实现一个接口,然后将该接口注入SomeClassCaller ,而不是具体类。

在Composition Root中,您可以连接对象图:

 var scc = new SomeClassCaller( new SomeClass( new MyLogger(), new SomeOtherClass())); 

您不需要DI容器来执行此操作,但如果您愿意,可以使用一个。