简体   繁体   中英

Only use a DI-container at the application start?

normally, I'll use a dependency injection container (unity) in c# like this example:

class SomeClass
{
    private readonly ILogger _logger;

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

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

Yesterday, I've read some articles about correct dependency injection with a di container. After this, I know that my example is totally bad. This is not dependency injection this is just something like a service locator.

Okay, how to solve this? I think with constructor injection you can solve this problem easily:

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

Now I have the correct implementation of the dependency injection principle. But how to wire up all these dependencies? I have a caller class which resolve all the required decencies of the class "SomeClass":

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

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

But this example still use a dependency container as a service locator, which is bad. In nearly every article about this, I've read, that the dependency container should only be used, at the application root/entry points, is this correct?

That means, no class should have the ability the resolve some dependencies with a "service locator" on the fly, like the logger. I've to inject the ILogger into nearly every class through the constructor, to avoid this problem, correct? This way feels really bad, if I take the ILogger through maybe 10 classes into every constructor, isn't it?

So, I've to use a dependencies container only, if I've a complex dependencie graph?

Can someone give me an example how it looks like, if you use a dependency container, only at the root of an application?

If SomeClassCaller needs SomeClass , inject it:

public class SomeClassCaller
{
    private readonly SomeClass someClass;

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

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

This is an example of a Concrete Dependency . Commonly, though, you could let SomeClass implement an interface, and then inject that interface into SomeClassCaller , instead of the concrete class.

In the Composition Root you can wire up your object graph:

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

You don't need a DI Container to do this, but you can use one if you like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM