Mi tipo de proyecto preferido en .NET son las aplicaciones de consola ya que me permiten programar rápido y sin complicaciones centrándome en lo más importante que, para mí, es automatizar trabajo para ahorrar tiempo en tareas repetitivas. Como buen programador, cualquier proceso repetitivo que me lleve más de cinco minutos es candidato a ser automatizado y, para ello, lo más simple y efectivo es una aplicación de consola en C#.
Otro de los motivos por los que elijo utilizar una aplicación de consola con C# es porque no requiere de un servidor web o infraestructura en Azure, simplemente la publico como portable y después la utilizo en mi ordenador con un doble click.
Uno de los pasos que suelo realizar en este tipo de desarrollos express es añadir inyección de dependencias en la aplicación de consola C# por el mismo motivo de antes, es decir, para que el desarrollo sea más rápido, cómodo y limpio.
Este artículo no es más que una guía personal con todos los pasos necesarios para añadir a una aplicación de consola inyección de dependencias para que la puedas consultar siempre que lo necesites.
Código de ejemplo completo con proyecto de tipo consola
Vamos a comenzar con un proyecto de ejemplo en .NET 8, C# y tipo de proyecto «Console» creado a través de Visual Studio o VSCode.
En primer lugar tenemos la clase Program que contiene dos llamadas a dos métodos de la clase Core:
using ConsoleApp1;
internal class Program
{
private static void Main(string[] args)
{
Core core = new Core();
core.Method1();
core.Method2();
}
}En segundo lugar tenemos la clase Core o núcleo de nuestra aplicación de consola C# con dos métodos distintos que llaman al servicio de base de datos para obtener información y mostrarla por pantalla:
using ConsoleApp1.Services;
namespace ConsoleApp1
{
public class Core
{
public void Method1()
{
IServiceDatabase service = new ServiceDatabase1();
Console.WriteLine("Core.Method1: " + service.GetData());
}
public void Method2()
{
IServiceDatabase service = new ServiceDatabase1();
Console.WriteLine("Core.Method2: " + service.GetData());
}
}
}A continuación tenemos una interfaz IServiceDatabase para definir los métodos que accederán a la base de datos:
namespace ConsoleApp1.Services
{
public interface IServiceDatabase
{
public string GetData();
}
}Y finalmente tenemos dos implementaciones idénticas de la interfaz, ServiceDatabase1 y ServiceDatabase2, como puedes observar lo único que cambia es la forma de implementar el método GetData, en cada caso se devuelve una información distinta:
namespace ConsoleApp1.Services
{
public class ServiceDatabase1 : IServiceDatabase
{
public string GetData()
{
return "ServiceDatabase1.GetData";
}
}
}
namespace ConsoleApp1.Services
{
public class ServiceDatabase2 : IServiceDatabase
{
public string GetData()
{
return "ServiceDatabase2.GetData";
}
}
}Si ya conoces la inyección de dependencias te habrás dado cuenta de que este es el esquema típico donde podemos utilizarla para tener un código más limpio y mantenible y mejorar la velocidad de desarrollo en el caso de que tengamos que cambiar la implementación de algún servicio.
Pensemos un momento, ¿qué ocurre si quiero utilizar en toda mi aplicación la implementación ServiceDatabase2 en vez de ServiceDatabase1?, pues debo cambiar todos los sitios donde se inicialize y, en vez de llamar a IServiceDatabase service = new ServiceDatabase1(); debo llamar a IServiceDatabase service = new ServiceDatabase2();. En este ejemplo solo son dos líneas, pero en un proyecto real pueden ser cientos de líneas y no es nada práctico, penaliza el tiempo de desarrollo.
¿Por qué utilizar inyección de dependencias?
Dada la reflexión anterior vamos a enumerar algunas de las ventajas de utilizar inyección de dependencias en cualquier proyecto, independientemente de su tipo, lenguaje y framework:
- Modificaciones de código más rápidas, siguiendo el ejemplo de código anterior hemos podido comprobar que si no tenemos inyección de dependencias y queremos modificar la implementación de un servicio deberemos tocar cientos de líneas de código.
Sin embargo, utilizando este método y si se hace correctamente, hacer una modificación consiste únicamente en modificar una línea como veremos a continuación, nada más. - Mayor velocidad de desarrollo, si queremos utilizar la implementación de un servicio concreto simplemente tendremos que inicializarlo una sola vez y después utilizarlo en las clases que necesitemos añadiéndolo a su constructor. Evitaremos mucho código redundante o repetitivo ya que no tendremos tantos
new()como antes. - Código más limpio o clean code, al ahorrarnos líneas de código éste estará más limpio y, como consecuencia, será más entendible.
- Desarrollo más cómodo, este punto se deriva de todos los anteriores, si el código está más limpio y las modificaciones o inserciones de nuevos servicios son más rápidas, el desarrollo se vuelve mucho más liviano.
¿Cómo utilizar inyección de dependencias en aplicación de consola C#?
Ahora es cuando viene lo divertido ya que vamos a poner en práctica todo lo anterior. Partiremos del código de ejemplo completo donde no tenemos nada y vamos a seguir los pasos para utilizar inyección de dependencias en aplicación de consola con C#:
- Asegúrate de que la clase
Programtiene la estructura correcta. Generalmente, cuando creamos una aplicación de consola, la claseProgramviene sin el métodoMain, asegúrate de que sea similar al siguiente código:internal class Program { private static void Main(string[] args) { Core core = new Core(); core.Method1(); core.Method2(); } } - Instala el paquete
Microsoft.Extensions.DependencyInjectiona través del administrador de paquetes NuGet. - Cambia la clase
Programpara registrar los servicios que necesites, incluida la claseCoreo principal. No te olvides de añadir la línea deusing Microsoft.Extensions.DependencyInjection;:using ConsoleApp1; using ConsoleApp1.Services; using Microsoft.Extensions.DependencyInjection; internal class Program { private static void Main(string[] args) { // Register services var services = new ServiceCollection(); services.AddSingleton<IServiceDatabase, ServiceDatabase1>(); services.AddSingleton<Core>(); var serviceProvider = services.BuildServiceProvider(); // Call core methods Core core = serviceProvider.GetService<Core>(); core.Method1(); core.Method2(); } } - Modifica la clase
Coreo principal para que reciba, por inyección de dependencias, el servicio de base de datos o el que corresponda:using ConsoleApp1.Services; namespace ConsoleApp1 { public class Core { // Get the service database instance through dependency injection private IServiceDatabase _serviceDatabase; public Core(IServiceDatabase serviceDatabase) { _serviceDatabase = serviceDatabase; } // Methods from core public void Method1() { Console.WriteLine("Core.Method1: " + _serviceDatabase.GetData()); } public void Method2() { Console.WriteLine("Core.Method2: " + _serviceDatabase.GetData()); } } } - Comprueba que la inyección de dependencias es correcta, para ello ejecuta tu programa y verifica que el output es el del servicio 1 y no el del servicio 2:
Core.Method1: ServiceDatabase1.GetData Core.Method2: ServiceDatabase1.GetData - Cambia la inyección de dependencias para que se inyecte el servicio 2 en vez del 1. Para ello, dentro de la clase
Program, modifica la líneaservices.AddSingleton<IServiceDatabase, ServiceDatabase1>();porservices.AddSingleton<IServiceDatabase, ServiceDatabase2>();. - Verifica que el cambio es correcto, es decir, ahora el output debe ser el siguiente:
Core.Method1: ServiceDatabase2.GetData Core.Method2: ServiceDatabase2.GetData
Observa cuidadosamente que las ventajas de la inyección de dependencias que hemos comentado anteriormente se cumplen puesto que, para cambiar la implementación de un servicio en toda la aplicación, solo hemos tenido que modificar una línea.
En algunos sitios de Internet encontrarás que es necesario el paquete Microsoft.Extensions.Hosting y un código similar a var host = Host.CreateDefaultBuilder(); no es en absoluto necesario, al menos para añadir de manera sencilla y efectiva inyección de dependencias a tu aplicación de consola C#, lo único que hará será complicar tu código innecesariamente.
Finalmente os dejo los enlaces al código completo de los ejemplos utilizados en esta guía paso a paso:
- Enlace al respositorio base sin inyección de dependencias configurada.
- Enlace al repositorio con el código de la aplicación de consola C# e inyección de dependencias configurada.




