A IServiceCollectioninterface é usada para criar um contêiner de injeção de dependência. Depois de totalmente construído, ele é composto por uma IServiceProviderinstância que você pode usar para resolver serviços. Você pode injetar um IServiceProviderem qualquer classe. As classes IApplicationBuildere também HttpContextpodem fornecer o provedor de serviços, por meio de suas propriedades ApplicationServicesou RequestServices.
IServiceProviderdefine um GetService(Type type)método para resolver um serviço:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
Existem também vários métodos de extensão de conveniência disponíveis, como serviceProvider.GetService<IFooService>()(adicione um usingparaMicrosoft.Extensions.DependencyInjection ).
Resolvendo serviços dentro da classe de inicialização
Injetando dependências
Provedor de serviço do tempo de execução pode injetar certos serviços para o construtor da Startupclasse, tais como IConfiguration,
IWebHostEnvironment( IHostingEnvironmentem pré-versões 3.0), ILoggerFactorye IServiceProvider. Observe que a última é uma instância criada pela camada de hospedagem e contém apenas os serviços essenciais para iniciar um aplicativo .
O ConfigureServices()método não permite a injeção de serviços, apenas aceita um IServiceCollectionargumento. Isso faz sentido porque ConfigureServices()é onde você registra os serviços exigidos pelo seu aplicativo. No entanto, você pode usar serviços injetados no construtor da inicialização aqui, por exemplo:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
Quaisquer serviços registrados ConfigureServices()podem ser injetados no Configure()método; você pode adicionar um número arbitrário de serviços após o IApplicationBuilderparâmetro:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
Resolução manual de dependências
Se você precisar resolver serviços manualmente, use preferencialmente o ApplicationServicesfornecido por IApplicationBuilderno Configure()método:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
É possível passar e usar diretamente um IServiceProviderno construtor de sua Startupclasse, mas, como acima, ele conterá um subconjunto limitado de serviços e, portanto, possui utilidade limitada:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
Se você precisar resolver serviços no ConfigureServices()método, será necessária uma abordagem diferente. Você pode criar um intermediário a IServiceProviderpartir da IServiceCollectioninstância que contém os serviços que foram registrados até aquele 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>();
}
Observação:
geralmente você deve evitar resolver serviços dentro do ConfigureServices()método, pois esse é realmente o local em que você está configurando os serviços de aplicativo. Às vezes, você só precisa acessar uma IOptions<MyOptions>instância. Você pode fazer isso vinculando os valores da IConfigurationinstância a uma instância de MyOptions(que é essencialmente o que a estrutura de opções faz):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
A resolução manual de serviços (aka Service Locator) é geralmente considerada um antipadrão . Embora tenha seus casos de uso (para estruturas e / ou camadas de infraestrutura), você deve evitá-lo o máximo possível.