A IServiceCollection
interface é usada para criar um contêiner de injeção de dependência. Depois de totalmente construído, ele é composto por uma IServiceProvider
instância que você pode usar para resolver serviços. Você pode injetar um IServiceProvider
em qualquer classe. As classes IApplicationBuilder
e também HttpContext
podem fornecer o provedor de serviços, por meio de suas propriedades ApplicationServices
ou RequestServices
.
IServiceProvider
define 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 using
paraMicrosoft.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 Startup
classe, tais como IConfiguration
,
IWebHostEnvironment
( IHostingEnvironment
em pré-versões 3.0), ILoggerFactory
e 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 IServiceCollection
argumento. 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 IApplicationBuilder
parâ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 ApplicationServices
fornecido por IApplicationBuilder
no Configure()
método:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
É possível passar e usar diretamente um IServiceProvider
no construtor de sua Startup
classe, 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 IServiceProvider
partir da IServiceCollection
instâ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 IConfiguration
instâ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.