Cómo usar la interfaz IServiceProvider en ASP.NET Core

IServiceProvider es una parte fundamental del sistema de inyección de dependencias (DI) integrado en ASP.NET Core. Permite resolver instancias de servicios en tiempo de ejecución, lo cual es útil para lógica condicional o cuando no se conocen las dependencias en tiempo de compilación.

Crear un proyecto de ejemplo

  1. Abre Visual Studio 2022.
  2. Crea un nuevo proyecto y selecciona “ASP.NET Core Web API”.
  3. Establece el framework como .NET 8.0 (LTS).
  4. Opciones:
  • Marca “Use Controllers”.
  • Deja sin marcar: “Authentication”, “Enable OpenAPI”, “Configure for HTTPS”, y “Enable Docker”.

Fundamentos de Inyección de Dependencias

  • Inyección por constructor: Utilízala cuando las dependencias se conocen en tiempo de compilación.
    public class MiServicio
    {
      public MiServicio(IMiDependencia dep) { ... }
    }
    
  • Uso de IServiceProvider: Úsalo cuando las dependencias pueden variar en tiempo de ejecución.
    if (condicion)
    {
      var servicio = _provider.GetRequiredService<IMiLogger>();
    }
    

Registrar servicios en Program.cs

builder.Services.AddTransient<IMiServicio, MiServicio>();
builder.Services.AddScoped<IMiServicioScoped, ServicioScoped>();
builder.Services.AddSingleton<IMiSingleton, SingletonServicio>();

Inyectar y usar IServiceProvider

public class HomeController : Controller
{
    private readonly IServiceProvider _provider;

    public HomeController(IServiceProvider provider)
    {
        _provider = provider;
    }

    public IActionResult Index()
    {
        var logger = _provider.GetService<IMiLogger>();
        ...
    }
}

Es recomendable usar GetRequiredService<T>() en lugar de GetService<T>(), ya que este último puede devolver null si el servicio no está registrado, lo cual puede causar errores silenciosos.

Tiempos de vida de los objetos

Tiempo de vidaAlcance
TransientSe crea una nueva instancia cada vez que se solicita
ScopedUna instancia por cada solicitud HTTP
SingletonUna única instancia durante toda la vida de la aplicación

Crear ámbitos (scopes)

Con IServiceProvider

using (var scope = _provider.CreateScope())
{
    var servicio = scope.ServiceProvider.GetRequiredService<IMiServicioScoped>();
    await servicio.EjecutarAsync();
}

Con IServiceScopeFactory

using (var scope = _scopeFactory.CreateScope())
{
    var contexto = scope.ServiceProvider.GetRequiredService<LogDbContext>();
    contexto.Add(new LogMessage { Message = "Prueba", IpAddress = "127.0.0.1" });
    await contexto.SaveChangesAsync();
}

Buenas prácticas

  • Prefiere la inyección por constructor antes que el uso directo de IServiceProvider, salvo que necesites resolver servicios de forma dinámica.
  • Usa GetRequiredService<T>() en lugar de GetService<T>() para evitar errores silenciosos.
  • No elimines manualmente los servicios resueltos; deja que el contenedor los administre.
  • Para servicios que se ejecutan fuera del contexto HTTP, como servicios en segundo plano, crea ámbitos manualmente con CreateScope().

Comprender y aplicar correctamente IServiceProvider te permitirá desarrollar aplicaciones ASP.NET Core más flexibles, modulares y fáciles de mantener. Es una herramienta poderosa cuando se utiliza de manera adecuada, especialmente para casos en los que no puedes usar inyección por constructor.

Vistas: 0