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

标签 c# dependency-injection

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

class SomeClass
{
    private readonly ILogger _logger;

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

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

昨天,我读了一些关于使用 di 容器进行正确依赖注入(inject)的文章。在此之后,我知道我的例子完全不好。这不是依赖注入(inject),这只是类似服务定位器的东西。

好的,这个问题怎么解决呢?我认为通过构造函数注入(inject)可以轻松解决这个问题:

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

现在我已经正确实现了依赖注入(inject)原理。 但如何连接所有这些依赖关系呢?我有一个调用者类,它解决了“SomeClass”类所需的所有礼仪:

class SomeClassCaller
{
    public void DoSomething()
    {
        var logger = DependencyContainer.Resolve<ILogger>();
        var someOtherClass = DependencyContainer.Resolve<...>();

        var someClass = new SomeClass(logger, someOtherClass);
        someClass.DoSomething();
    }
}

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

这意味着,任何类都不应具有通过“服务定位器”动态解决某些依赖关系的能力,例如记录器。我必须通过构造函数将 ILogger 注入(inject)到几乎每个类中,以避免这个问题,对吗?如果我将 ILogger 通过大约 10 个类放入每个构造函数中,这种方式感觉非常糟糕,不是吗?

那么,如果我有一个复杂的依赖关系图,我必须仅使用依赖关系容器?

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

最佳答案

如果SomeClassCaller需要SomeClass,则注入(inject)它:

public class SomeClassCaller
{
    private readonly SomeClass someClass;

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

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

这是 Concrete Dependency 的示例。不过,通常情况下,您可以让 SomeClass 实现一个接口(interface),然后将该接口(interface)注入(inject)到 SomeClassCaller 中,而不是具体的类中。

Composition Root您可以连接您的对象图:

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

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

关于c# - 仅在应用程序启动时使用 DI 容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35650884/

相关文章:

c# - Linq to XML 的条件输出

java - 如何在使用 GIN 注入(inject)期间传播值

c# - 如何获取可用系统内存的大小?

c# - ConcurrentDictionary - 损坏的字典或错误的代码?

c# - DictionaryBase 到泛型。

c# - Task.Factory.StartNew 与异步方法

c# - 如何让ServiceProvider对手动创建的对象调用Dispose?

c# - 使用 Controller 类以外的类进行依赖注入(inject)

java - 如何在一个类中@Inject两个相似的实现?

java - Dagger:多次注入(inject)的类中没有可注入(inject)成员