Mart Broekkamp
Mart Broekkamp

Reputation: 139

Why not inject IServiceProvider instead of each individual dependency?

I am wondering why one wouldn't explicitly use the IServiceProvider to resolve dependencies over injecting each dependency individually. In other words, why use this approach:

public class A 
{
    private B _b;
    private C _c;
    private D _d;
    private E _e;

    public A(B b, C c, D d, E e)
    {
        _b = b;
        _c = c;
        _d = d;
        _e = e;
    }
}

and not this:

public class A 
{
    private B _b;
    private C _c;
    private D _d;
    private E _e;

    public A(IServiceProvider sp)
    {
        _b = (b) sp.GetService(typeof(b));
        _c = (c) sp.GetService(typeof(c));
        _d = (d) sp.GetService(typeof(d));
        _e = (e) sp.GetService(typeof(e));
    }
}

Note that I may not call GetService for all of the types, some of the types may be effectively optional (i.e. sometimes used, sometimes not used).

The advantage of the second approach being that we don't need to make a change in every place where we are calling the constructor of A if there is a change in the dependencies of A, and we don't need to have all of the dependencies already available wherever we are calling the constructor.

MS seems to recommend against this in the following article: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2#recommendations They mention to avoid using the service locator pattern instead of DI, but aren't we still using DI here? Is the same thing not happening in the background anyway?

Upvotes: 8

Views: 1869

Answers (2)

Timmeh
Timmeh

Reputation: 408

This is called the Service Locator Pattern -> https://en.wikipedia.org/wiki/Service_locator_pattern

It has some advantages and disadvantages (described in the article), however it is widely viewed as an anti-pattern.


You state that you are calling constructors yourself (as in new SomeService(...) I'm guessing), which is a sign of not using DI (or only partially).

Upvotes: 1

aframestor
aframestor

Reputation: 196

There are several reasons. When you use dependency injection, you are giving the DI container responsibility for preparing your dependencies for you. The classes shouldn't care about how your dependencies are created. If you switch to a different DI library you would have to change constructors in all of your classes.

Another small concern is that you would have to create a mock for your service container in every unit test which is not a huge issue but definitely something that could be annoying.

Lastly your code will become very strange when you have to pass dependencies to nested classes, not to mention any time you want to have inheritance.

Upvotes: 5

Related Questions