Dependency Inversion

 

We've now reached the last point of the SOLID principles, which is dependency inversion.

In .NET we comply with this principle using dependency injection. It's most common to see dependency inversion in web applications, but we can also use it in console applications.

The only difference is that, starting from .NET Core, when we create a web application, the class that contains the dependencies is created by default and it is very easy to add new dependencies to it, whereas in a console application, you have to set it up manually.

Later on, we'll see how both approaches work.

 

1 - What is the dependency inversion principle.

The dependency inversion principle is used to allow us to create classes that are coupled to each other in a simple way.

This principle tells us that we should separate logic into modules or services that can be reused, so that if we need to modify them, only those services will be affected.

This way, we also remove some of the responsibility from our class.

All the SOLID principles are closely related; the dependency inversion principle relies on interfaces, which we have seen in previous modules.

 

2 - Using dependency inversion

As I mentioned earlier, in .NET the way to use dependency inversion is through dependency injection.

And what we have to do, as its name suggests, is inject these dependencies into our services.

 

To do this, we use the constructor.

public class AlmacenamientoFichero : IAlmacenamiento
{
    readonly IFicheroInformacion _ficheroInformacion;

    public AlmacenamientoFichero(IFicheroInformacion ficheroInformacion)
    {
        _ficheroInformacion = ficheroInformacion;
    }
    //Resto de métodos
}

As we can see, we're injecting the IFicheroInformacion interface through the constructor. This interface contains the method that allows us to check the information on a file. But we “don’t know” how it's implemented, or the dependencies of that other class, because it's abstracted through an interface.

 

As you can see, now the constructor takes a parameter, and when we instantiate the class, we should provide it. However, we won't actually do that manually, since all our code will be structured following the dependency inversion principle.

So we need to inject dependencies into all our classes.

public class ArticulosServicio
{
    private readonly Cache _cache;
    private readonly ILogging _logging;
    private readonly IAlmacenamiento _almacenamiento;

    public ArticulosServicio(IAlmacenamiento almacenamiento, ILogging logging, Cache cache)
    {
        _logging = logging;
        _almacenamiento = almacenamiento;
        _cache = cache;
    }

   //resto de métodos
    
}

 

3 - Dependency injection in .NET

Since I will be writing a more detailed post about dependency injection in the future, I'll just give a brief overview here, so that our code knows which class each interface refers to.

 

3.1 - Dependency injection in ASP.NET Core

Since the release of Net Core, we have a dependency container for asp.net in the core of the system, which we can access from the startup.cs file/class, in the ConfigureServices method. We just need to specify services.AddScoped<Interface, Class>.

This way, when the code reaches a constructor containing that interface, it will know which class it's referring to.

services.AddScoped<IAlmacenamiento, AlmacenamientoSQL>()
    .AddScoped<ILogging, Logging>()
    .AddScoped<DBRepository>()
    .AddScoped<Cache>();

 

3.2 - Dependency injection in a console application.

The goal is the same as in the ASP.NET example, but in this case, we need to build the dependency container ourselves.

For this, we need to use the following two packages:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

This way, we have access to the ServiceCollection class, which lets us build our dependencies with the BuildServiceProvider method.

//Base
var serviceProvider = new ServiceCollection()
    .AddScoped<Interface, Clasesservicio>()
    .BuildServiceProvider();

var servicio = serviceProvider
    .GetService<Interface>();


//Ejemplo en nuestro código
var serviceProvider = new ServiceCollection()
    .AddScoped<IAlmacenamiento, AlmacenamientoFichero>()
    .BuildServiceProvider();

var servicio = serviceProvider
    .GetService<IAlmacenamiento>();

note: we will see the difference between scoped, singleton, and transient in another post.

 

4 - Benefits of implementing dependency inversion

Thanks to dependency inversion, we can create smaller and more independent classes, which also allows us to reuse logic very easily. In my opinion, this is its greatest advantage.

Adding dependency inversion provides flexibility and stability when developing our applications, since we'll be more confident when adding new features, etc.

As a final major advantage, using dependency inversion allows us to create unit tests much easier, enabling us to create mocks of those same services.

 

Conclusion

Finally, I'll say yes, we should implement dependency inversion in all our projects because it gives us services that are more reusable and easier to implement in other services.

With this post, we've covered all the SOLID principles, and by following them strictly we can create robust applications that are well-structured to adapt to future changes.

 

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café