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);
}
Разрешение сервисов вручную (он же Сервисный локатор) обычно считается антишаблоном . Хотя у него есть свои варианты использования (для каркасов и / или инфраструктурных уровней), вы должны избегать его в максимально возможной степени.