IServiceCollection
Интерфейс используется для построения контейнера инъекции зависимостей. После полной сборки он объединяется с IServiceProvider
экземпляром, который можно использовать для разрешения служб. Вы можете ввести IServiceProvider
в любой класс. Эти IApplicationBuilder
и HttpContext
классы могут предоставить поставщик услуг , а также, с помощью их ApplicationServices
или RequestServices
свойств , соответственно.
IServiceProvider
определяет GetService(Type type)
метод для разрешения службы:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
Есть также несколько удобных методов расширения, таких как serviceProvider.GetService<IFooService>()
(добавить using
для Microsoft.Extensions.DependencyInjection
).
Разрешение служб внутри класса запуска
Внедрение зависимостей
Хостинг-провайдер среды выполнения может внедрить определенные сервисы в конструктор Startup
класса, например IConfiguration
,
IWebHostEnvironment
( IHostingEnvironment
в версиях до 3.0) ILoggerFactory
и IServiceProvider
. Обратите внимание, что последний является экземпляром, созданным на уровне хостинга, и содержит только основные службы для запуска приложения .
ConfigureServices()
Метод не позволяет инъекционным услуги, она только принимает IServiceCollection
аргумент. Это имеет смысл, потому что ConfigureServices()
именно здесь вы регистрируете сервисы, необходимые для вашего приложения. Однако вы можете использовать сервисы, добавленные в конструктор запуска, например:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
Любые услуги, зарегистрированные в, ConfigureServices()
могут затем быть введены в Configure()
метод; Вы можете добавить произвольное количество сервисов после IApplicationBuilder
параметра:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
Разрешение зависимостей вручную
Если вам необходимо разрешить службы вручную, предпочтительно использовать ApplicationServices
предоставленный IApplicationBuilder
в Configure()
методе:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
Можно передать и напрямую использовать IServiceProvider
конструктор в вашем Startup
классе, но, как указано выше, он будет содержать ограниченное подмножество сервисов и, следовательно, будет иметь ограниченную полезность:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
Если вам необходимо разрешить службы в ConfigureServices()
методе, требуется другой подход. Вы можете создать промежуточное звено IServiceProvider
из IServiceCollection
экземпляра, который содержит службы, которые были зарегистрированы до этого момента :
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>();
}
Обратите внимание: как
правило, вам следует избегать разрешения служб внутри ConfigureServices()
метода, поскольку именно здесь вы настраиваете службы приложения. Иногда вам просто нужен доступ к IOptions<MyOptions>
экземпляру. Вы можете сделать это, связав значения из IConfiguration
экземпляра с экземпляром MyOptions
(что, по сути, и делает инфраструктура опций):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
Разрешение сервисов вручную (он же Сервисный локатор) обычно считается антишаблоном . Хотя у него есть свои варианты использования (для каркасов и / или инфраструктурных уровней), вы должны избегать его в максимально возможной степени.