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

时间:2016-02-26 11:46:28

标签: c# dependency-injection

通常,我会在c#中使用依赖注入容器(unity),如下例所示:

/Users/sunnyjain/Desktop/vernemq/_build/dev1/rel/vernemq/bin

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

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

class SomeClass
{
    private readonly ILogger _logger;

    public SomeClass()
    {
        _logger = DependencyContainer.Resolve<ILogger>();
    }

    public void DoSomething()
    {
        var someOtherClass = DependencyContainer.Resolve<...>();
        someOtherClass().whatElseEver();
    }
}

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

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();
    }
}

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

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

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

如果您使用依赖项容器,只有在应用程序的根目录下,有人能给我一个示例吗?

1 个答案:

答案 0 :(得分:3)

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

public class SomeClassCaller
{
    private readonly SomeClass someClass;

    public SomeClassCaller(SomeClass someClass)
    {
        this.someClass = someClass;
    }

    public void DoSomething()
    {
        this.someClass.DoSomething();
    }
}

这是Concrete Dependency的示例。通常,您可以让SomeClass实现一个接口,然后将该接口注入SomeClassCaller,而不是具体的类。

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

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

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