Dependency Injection - The last but not least
https://stackify.com/dependency-injection/

Dependency Injection - The last but not least


No alt text provided for this image

Dependency Injection is the last principle from the acronym SOLID.

I don't know, but I believe that Dependency Injection is one of the most powerful principles in software development.

With Dependency Injection, we can test our apps without caring about actual implementations, making our software cleaner, safer, and more flexible.

With it, we can quickly create multi-tenancy apps. However, what I bring today is basic but essential, and sometimes we need help understanding the differences.

In a nutshell, Dependency injection works better together with the principle IoC(Inversion of Control).

With Ioc, we usually will see the dependencies on the constructor of our classes. In this case, it will be necessary to provide the implementation when we want to create this object.

Service Provider

And finally, we have our service provider to make this easier for us.

The service provider will store every configuration that you add to ServiceCollection and provides it to our application every time we asked for.

How could we add something to this collection?

builder.Services.AddTransient<ITransientService, TransientService>();
builder.Services.AddScoped<IScopedService, ScopedService>();? ? 
builder.Services.AddSingleton<ISingletonService, SingletonService>();        

Remember to register services before the application is built to add the services to the ServiceCollection correctly.

In .net, we have three ways that we can register one dependency. Transient, Scoped, and Singleton.

I created a simple web API for this sample to inject these three services.

? ? public interface IServiceBase
? ? {
? ? ? ? DateTime CreatedAt { get; set; }
? ? ? ? Guid Id { get; set; }
? ? }


? ? public class ServiceBase : IServiceBase
? ? {
? ? ? ? public Guid Id { get; set; } = Guid.NewGuid();
? ? ? ? public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
? ? }


? ? public interface IScopedService : IServiceBase { }
? ? public class ScopedService : ServiceBase, IScopedService
? ? {
? ? }


? ? public interface ITransientService : IServiceBase { }
? ? public class TransientService : ServiceBase, ITransientService
? ? {
? ? }


? ? public interface ISingletonService : IServiceBase { }
? ? public class SingletonService : ServiceBase, ISingletonService
? ? {
? ? }        

And here are the injection.

builder.Services.AddTransient<ITransientService, TransientService>();
builder.Services.AddScoped<IScopedService, ScopedService>();
builder.Services.AddSingleton<ISingletonService, SingletonService>();        

And the HomeController has these simple codes to understand the differences.

? ? [ApiController]
? ? [Route("[controller]")]
? ? public class HomeController : ControllerBase
? ? {
? ? ? ? private readonly IServiceProvider _serviceProvider;


? ? ? ? public HomeController(IServiceProvider serviceProvider)
? ? ? ? {
? ? ? ? ? ? _serviceProvider = serviceProvider;
? ? ? ? }


? ? ? ? [HttpGet("GetTransient")]
? ? ? ? public IEnumerable<IServiceBase> GetTransient()
? ? ? ? {
? ? ? ? ? ? var list = new List<IServiceBase>();
? ? ? ? ? ? using (var serviceScope = _serviceProvider.CreateScope())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 5; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? list.Add(serviceScope.ServiceProvider.GetService<ITransientService>());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return list;
? ? ? ? }


? ? ? ? [HttpGet("GetScoped")]
? ? ? ? public IEnumerable<IServiceBase> GetScoped()
? ? ? ? {
? ? ? ? ? ? var list = new List<IServiceBase>();
? ? ? ? ? ? using (var serviceScope = _serviceProvider.CreateScope())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 5; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? list.Add(serviceScope.ServiceProvider.GetService<IScopedService>());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return list;
? ? ? ? }


? ? ? ? [HttpGet("GetSingleton")]
? ? ? ? public IEnumerable<IServiceBase> GetSingleton()
? ? ? ? {
? ? ? ? ? ? var list = new List<IServiceBase>();
? ? ? ? ? ? using (var serviceScope = _serviceProvider.CreateScope())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 5; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? list.Add(serviceScope.ServiceProvider.GetService<ISingletonService>());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return list;
? ? ? ? }
? ? }        

?Transient

Dependency injected as a Transient will always create a new implementation.

No alt text provided for this image

Scoped

Dependency injected as a Scoped will create a new implementation for scope.

It is a web API application. Then we have a different scope for requests. We can see that when we call the method again, the service provider creates a new implementation.

No alt text provided for this image


Singleton

Last but not least.

Singleton is created once when the application is built, and we will have the same instance in every place we call them.

No alt text provided for this image

This is as easy as it seems.

This post can help someone.

And please USE the dependency correctly. Injecting everything that the class needs to exist on the constructor does not do, like me injecting the provider. This can introduce issues on runtime and become harder to create tests.

That's it.

I hope to write to you all soon.


References

要查看或添加评论,请登录

Cristian Lopes的更多文章

  • Tailwind 'the savior of the dev backend'

    Tailwind 'the savior of the dev backend'

    The most popular CSS framework. Tailwind makes any design easy to build.

  • NET MAUI - AWS DynamoDB

    NET MAUI - AWS DynamoDB

    Hey guys. Today I will bring two of my passions, mobile apps, mainly with Xamarin or now .

  • MediatR -Além do básico[PT-BR]

    MediatR -Além do básico[PT-BR]

    RequestHandler, NotificiationHandler, and StreamRequestHandler. Você já ouviu falar sobre MediatR? Se você é um…

社区洞察

其他会员也浏览了