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)
Hi! Why not only use Singleton classes? What are the benefits using Scoped and Transient?
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!
If I have a Controller that takes a Service and that Service takes a Repository, how do I inject that Repository into the Service?
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:
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
withMySqlRepository
andMongoDbRepository
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!