Ejemplo de inyección de dependencias con C#

Explicaremos como funciona este patrón que es usado bastante en muchos frameworks actuales como ASP.NET MVC, Angular, Laravel, entre otros.

Rodríguez Patiño, Eduardo
2020-09-28 | 46,482 lecturas

Esta lección ha sido reescrita completamente otorgando otro ejemplo para aclarar de manera más simple el uso de dicho patrón.

¿Qué es?

Es un patrón de diseño que soluciona el problema del alto acoplamiento. Es decir, si en vez de que nuestra clase tenga la responsabilidad de instanciar las dependencias, nuestra recibirá las dependencias con las que se desea trabajar.

Ejemplo

Supongamos que tenemos el siguiente código.

class OrderService {
    private readonly EmailService _emailService;

    public OrderService () {
        _emailService = new EmailService();
    }
}

A simple vista este código no parece tener nada malo pero genera un fuerte acoplamiento.

Implementando Inyección de Dependencia

Desde mi punto de vista si es que hacemos un buen uso de este patrón vamos a crear un sistema modular. Pero para que pueda ser modular necesita trabajar un nivel de abstracción más alto; por eso, vamos hacer uso de interfaces.

class OrderService {
    private readonly IEmailService _emailService;

    public OrderService (
        IEmailService emailService) {
        _emailService = emailService;
    }
}

Han cambiado 2 cosas, la primera es que ahora reciben una interfaz en vez de una clase y la segunda es que ya no se instancia directamente de la clase.

¿Qué ganamos con esto?

Que nuestro código sea más modular.

Supongamos que hoy día trabajamos con MailChimp para enviar el correo, pero mañana por un tema de costos aparece otro provedor como SendInBlue que nos ofrece un mejor precio y nuestro CTO dice que vamos hacer uso de dicho proveedor.

Si nuestro código no se inyectará por el constructor y asimismo no fuera una interface, tendríamos que cambiar las dependencias de la clase EmailService en todo el proyecto.

En cambio, ahora quien cambiará la definición de dicha dependencia será el programa.

// hoy día
var orderService = new OrderService(
    new MailchimpService()
);

// mañana
var orderService = new OrderService(
    new SendInBlueService()
);

Tomen nota que tanto mailchimp como sendinblue deben implementar la misma interfaz para que se pueda resolver de manera polimórfica.

Conclusión

En pocas palabras la inyección de dependencia es cambiar el flujo de instanciamiento, en vez de crear dependencias dentro de nuestra clase, mejor que sea el programa quien define las dependencias y las inyecta a los constructores de nuestra clase.

Hay casos que no hace falta implementar una interfaz. Por ejemplo, a veces creo clases de configuración del proyecto como la que veremos a continuación.

class AppSetting {
    public string ConnectionString;
    public string AzureStorageConnectionString;
    public string CurrencyFormat;
}

Por lo cual, esta clase no necesita implementar una interfaz ya que, es una clase que usamos para configuración nada más.