DEV Community

JPBlancoDB
JPBlancoDB

Posted on

Dependency Injection in NetCore

Dependency Injection in NetCore

Dependency Injection [DI] is a pattern that gives the implementation of a class to an object without needing a Factory or the object knowing how to instantiate it with the intent to decoupling these objects.

We are going to describe the purposes of the three types of patterns available in NetCore: “Singleton”, “Scoped” and “Transient”.

The purpose of Singleton is to instantiate your object only once and then whenever you need that object, you will use the same implementation. This is useful for example for caching.

Then, we have Scoped. When it is applied your object will be instantiated once per request lifecycle. This is useful for example for Repositories or Services.

Lastly, we have Transient. This is the most common of the three because it is going to be instantiated whenever it is invoked.

In NetCore you define your DI inside Startup.cs on ConfigureServices method. Now, let’s see how you can define this.

Singleton:

services.AddSingleton<Interface, ImplementationClass>();

Scoped:

services.AddScoped<Interface, ImplementationClass>();

Transient:

services.AddTransient<Interface, ImplementationClass>();

You can read more about this pattern on:

https://martinfowler.com/articles/injection.html

If you have any doubt don’t hesitate to leave your comments or asking me ​​via Twitter.

Top comments (4)

Collapse
 
jcalixte profile image
Julien Calixte

Hi! Why not only use Singleton classes? What are the benefits using Scoped and Transient?

Collapse
 
jpblancodb profile image
JPBlancoDB

Hi Julien! So singleton classes only instantiate once, I would not use singleton as default because could cause you troubles. Don't think that it is going to be better for performance if you use your whole app as a singleton, on the contrary, I would recommend you if you are in doubt, just use transient as default.

One use case for singleton that I could think of right now is, for example, you have a configuration file and this does not change then you want to read it once at startup and then inject these values where is needed. Or for the service locator pattern, you could read more about this: Using a service locator.

My advice is, don't ever use singletons for classes that contain business logic.

I hope this gives you more insights into singletons!

Collapse
 
katnel20 profile image
Katie Nelson

If I have a Controller that takes a Service and that Service takes a Repository, how do I inject that Repository into the Service?

Collapse
 
jpblancodb profile image
JPBlancoDB

Hi Katie, that's a good question and sorry for not specify that in the post. So, in Startup.cs class you declare all the bindings for knowing which implementation needs to be resolved for each interface. For the actual dependency injection, you could do it by passing the members in the constructor of your class, an example:

// MyController.cs
[ApiController, Route("api/[controller]")]
public class MyController : BaseController 
{
    private readonly IMyService _myService;

    public MyController(IMyService myService)
    { 
        _myService = myService;
    }
}
// MyService.cs
public class MyService : IMyService
{
    private readonly IMyRepository _myRepository;

    public MyService(IMyRepository myRepository) -> here it gets injected
    { 
        _myRepository = myRepository;
    }
}

This is constructor injection (you also have other way like "field injection"). To summarize, you need to pass the interface via constructor and is going to be resolved to the desired class at runtime with whatever you have declared in your startup.

This allows you to have two different implementations but you are not coupled. One scenario could be that you have

IRepository with MySqlRepository and MongoDbRepository as implementations of that interface. Is recommended to always develop against an abstraction (in this case, IRepository) and resolve the desire implementation at runtime by any logic you need.

I hope this clarifies a little bit more. Let me know if it was helpful or if you need more info, I'm happy to help!