La IServiceCollection
interfaz se usa para construir un contenedor de inyección de dependencia. Una vez que está completamente construido, se compone de una IServiceProvider
instancia que puede usar para resolver servicios. Puede inyectar un IServiceProvider
en cualquier clase. Los IApplicationBuilder
y HttpContext
las clases pueden proporcionar el proveedor de servicio, así, a través de sus ApplicationServices
o RequestServices
propiedades respectivamente.
IServiceProvider
define un GetService(Type type)
método para resolver un servicio:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
También hay varios métodos de extensión de conveniencia disponibles, como serviceProvider.GetService<IFooService>()
(agregar un using
para Microsoft.Extensions.DependencyInjection
).
Resolviendo servicios dentro de la clase de inicio
Inyectando dependencias
Proveedor de alojamiento de servicio del tiempo de ejecución puede inyectar ciertos servicios en el constructor de la Startup
clase, tales como IConfiguration
,
IWebHostEnvironment
( IHostingEnvironment
en pre-3.0 versiones), ILoggerFactory
y IServiceProvider
. Tenga en cuenta que esta última es una instancia creada por la capa de alojamiento y contiene solo los servicios esenciales para iniciar una aplicación .
El ConfigureServices()
método no permite inyectar servicios, solo acepta un IServiceCollection
argumento. Esto tiene sentido porque ConfigureServices()
es donde registra los servicios requeridos por su aplicación. Sin embargo, puede utilizar los servicios inyectados en el constructor de la startup aquí, por ejemplo:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
Cualquier servicio registrado en ConfigureServices()
puede ser inyectado en el Configure()
método; Puede agregar un número arbitrario de servicios después del IApplicationBuilder
parámetro:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
Resolver dependencias manualmente
Si necesita resolver los servicios de forma manual, debe utilizar preferiblemente el ApplicationServices
proporcionado por IApplicationBuilder
en el Configure()
método:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
Es posible pasar y usar directamente un IServiceProvider
en el constructor de su Startup
clase, pero como se indica arriba , contendrá un subconjunto limitado de servicios y, por lo tanto, tiene una utilidad limitada:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
Si debe resolver los servicios en el ConfigureServices()
método, se requiere un enfoque diferente. Puede crear un intermediario IServiceProvider
desde la IServiceCollection
instancia que contiene los servicios que se han registrado hasta ese momento :
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFooService, FooService>();
// Build the intermediate service provider
var sp = services.BuildServiceProvider();
// This will succeed.
var fooService = sp.GetService<IFooService>();
// This will fail (return null), as IBarService hasn't been registered yet.
var barService = sp.GetService<IBarService>();
}
Tenga en cuenta: en
general, debe evitar resolver servicios dentro del ConfigureServices()
método, ya que este es realmente el lugar donde está configurando los servicios de la aplicación. A veces solo necesitas acceder a una IOptions<MyOptions>
instancia. Puede lograr esto vinculando los valores de la IConfiguration
instancia a una instancia de MyOptions
(que es esencialmente lo que hace el marco de opciones):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
La resolución manual de servicios (también conocido como Localizador de servicios) generalmente se considera un antipatrón . Si bien tiene sus casos de uso (para marcos y / o capas de infraestructura), debe evitarlo tanto como sea posible.
ConfigureServices()
método (conIServiceCollection
) o en cualquier lugar de la aplicación?