> Creando una aplicación de consola con Inyección de dependencias en .NET
Cuando creamos un proyecto de consola no tenemos disponible nada de lo que necesitamos para trabajar con inyección de dependencias, averiguaremos como hacerlo!

Probablemente en alguna ocasión nos hemos enfrentado a esta situación 🤔. Por lo general, (al menos en mi caso) solemos crear aplicaciones de consola cuando queremos probar algún fragmento de código o alguna idea nueva pero, puede ocurrir que luego de recorrer un largo trecho nos demos cuenta que queremos transferir este código a una aplicación real y que el escenario ideal hubiese sido asumir la inyección de dependencias de modo de no estar creando las dependencias en las clases sino inyectándolas desde afuera y que el código se amolde fácilmente a las buenas prácticas que queremos seguir a la hora de programar.
Cuando creamos este tipo de proyectos (Console App) en Visual Studio nos vemos frente al escenario de que no tenemos nada de lo que necesitamos configurado para poder hacerlo, solo tenemos una clase llamada Program.cs y eso es todo. La buena noticia es que usar inyección de dependencias es muy fácil, así que vamos a seguir el paso a paso para poder lograrlo. 💪
Vamos a crear un ejemplo sencillo que simule el guardado de empleados y su posterior presentación, por lo que crearemos un proyecto de consola y lo llamaremos "ConsoleAppDependencyInjection":
1) Lo primero que vamos necesitar es traer los paquetes necesarios para poder trabajar con inyección de dependencias 🚀. Para ello iremos al NuGet Package Manager y buscaremos el siguiente paquete: "Microsoft.Extensions.DependencyInjection", al momento actual la última versión estable y con la cual voy a trabajar es la 8.0.0, lo instalamos.
2) Lo segundo que buscaremos en el NuGet Package Manager es el paquete: "Microsoft.Extensions.Hosting" y al igual que el anterior la versión elegida será la 8.0.0, lo instalamos.
3) Una vez instalados los paquetes vamos a darle forma a nuestro proyecto con las siguientes carpetas 📁 y archivos:
En la raíz de nuestro proyecto crearemos las siguientes tres carpetas: Models, Interfaces, Services
También en la raíz del mismo crearemos una clase llamada Application.cs
Dentro de la carpeta "Models" crearemos una clase llamada "Employee.cs" con el siguiente código:
namespace ConsoleAppDendencyInjection.Models
{
public class Employee
{
public string Name { get; set; }
public string Lastname { get; set; }
public string JobTitle { get; set; }
public override string ToString()
{
return $"Hello, my name is {Name} {Lastname} and I am the {JobTitle} in Dunder Mifflin";
}
}
}
Como podemos ver el ejemplo en sencillo, son tres propiedades que hacen referencia al nombre, apellido y ocupación laboral de un empleado. También se hace un override del método ToString para personalizar un sencillo mensaje de saludo que usaremos luego.
Dentro de la carpeta Interfaces crearemos dos interfaces llamadas: "IApplication.cs" y "IEmployeeService.cs"
IApplication.cs:
namespace ConsoleAppDendencyInjection.Interfaces
{
public interface IApplication
{
void Start();
}
}
Tendrá un solo método que representará el inicio de nuestra aplicación.
IEmployeeService.cs:
using ConsoleAppDendencyInjection.Models;
namespace ConsoleAppDendencyInjection.Interfaces
{
public interface IEmployeeService
{
void AddEmployee(Employee employee);
void SayHello();
}
}
Tendrá dos métodos que representarán el agregado de empleados y a la acción de saludar.
Luego, dentro de la carpeta Services crearemos una clase llamada "EmployeeService.cs" con el siguiente código:
using ConsoleAppDendencyInjection.Interfaces;
using ConsoleAppDendencyInjection.Models;
namespace ConsoleAppDendencyInjection.Services
{
public class EmployeeService : IEmployeeService
{
private IList<Employee> _employeeList;
public EmployeeService()
{
_employeeList = new List<Employee>();
}
public void AddEmployee(Employee employee)
{
_employeeList.Add(employee);
}
public void SayHello()
{
foreach (var employee in _employeeList)
{
Console.WriteLine(employee.ToString());
}
}
}
}
Acá hacemos uso de la implementación nuestra interfaz IEmployeeService para agregar algo de lógica para el guardado de nuestros empleados y una simple iteración con un bucle foreach para sus respectivos saludos.
4) Ahora bien, tenemos nuestras interfaces, el punto de inicio de nuestra aplicación y nuestro servicio con su lógica solo nos hace falta lo más importante, configurar nuestro contenedor de servicios. Para ello vamos a nuestro Program.cs y pegaremos el siguiente código que les dejo a continuación:
using ConsoleAppDendencyInjection;
using ConsoleAppDendencyInjection.Interfaces;
using ConsoleAppDendencyInjection.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
IHost _host = Host.CreateDefaultBuilder().ConfigureServices(services =>
{
services.AddSingleton<IApplication, Application>();
services.AddScoped<IEmployeeService, EmployeeService>();
}).Build();
var app = _host.Services.GetRequiredService<IApplication>();
app.Start();
Explicación paso a paso de lo que estamos haciendo aquí:
A) Importación de los namespace necesarios para utilizar las clases e interfaces en el código.
B) Configuración del Host (Anfitrión). El método Host.CreateDefaultBuilder() nos permite crear un generador de host con la configuración predeterminada.
C) ConfigureServices(...). Este método define la configuración de servicios para el contenedor de inyección de dependencias. En este caso se están registrando dos servicios: uno Singleton, que significa que se crea una única instancia de "Application" en toda la aplicación y otra Scoped que registra la implementación de IEmployeeService como un servicio de ámbito, esto significa que se crea una nueva instancia por cada ámbito (generalmente, por solicitud en una aplicación web o por ejecución en una aplicación de consola como es nuestro caso).
D) Resolución de servicios y ejecución de la aplicación: con la línea "var app = _host.Services.GetRequiredService<IApplication>();" resolvemos el servicio IApplication del contenedor de servicios. En este caso se obtiene la instancia de la clase Application que se registró como singleton. Por último con "app.Start()" llamamos al método que da inicio y que posee la lógica principal de nuestra aplicación.
5) Por último, anteriormente creamos una clase llamada Application.cs, esta clase iniciará nuestra aplicación, introduciremos el siguiente código:
using ConsoleAppDendencyInjection.Interfaces;
using ConsoleAppDendencyInjection.Models;
namespace ConsoleAppDendencyInjection
{
public class Application : IApplication
{
private readonly IEmployeeService _employeeService;
public Application(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public void Start()
{
var employeeOne = new Employee
{
Name = "Dwight",
Lastname = "Schrute",
JobTitle = "Assistant Regional Manager"
};
var employeeTwo = new Employee
{
Name = "Michael",
Lastname = "Scott",
JobTitle = "Regional Manager"
};
_employeeService.AddEmployee(employeeOne);
_employeeService.AddEmployee(employeeTwo);
_employeeService.SayHello();
}
}
}
Como podemos ver, hacemos uso del potencial de la inyección de dependencias, inyectando en el constructor de nuestra clase el servicio EmployeeService el cual registramos en nuestro contenedor de servicios anteriormente. De esta manera se nos disponibiliza aquellos métodos establecidos en la firma de nuestra interfaz que nos darán la posibilidad de agregar empleados y permitirles su respectivo saludo.
Compilamos y este es el output que recibimos:
Hello, my name is Dwight Schrute and I am the Assistant Regional Manager in Dunder Mifflin
Hello, my name is Michael Scott and I am the Regional Manager in Dunder Mifflin
Si alguien entendió a primera lectura la referencia que estoy haciendo a una famosa serie me lo deja escrito en los comentarios. 😀
¡Y eso es todo! Espero que este pequeño tutorial haya sido de ayuda y puedan aprovechar el potencial de la inyección de dependencias en sus aplicaciones de consola en .NET. Ante cualquier duda no dejen de escribir en los comentarios, gracias por su tiempo ⭐.