Как вручную разрешить тип с помощью встроенной инфраструктуры внедрения зависимостей ASP.NET Core MVC?
Настройка контейнера достаточно проста:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddTransient<ISomeService, SomeConcreteService>();
}
Но как я могу решить ISomeService
без выполнения инъекций? Например, я хочу сделать это:
ISomeService service = services.Resolve<ISomeService>();
Там нет таких методов в IServiceCollection
.
ConfigureServices()
методе (сIServiceCollection
) или просто где-нибудь в приложении?Ответы:
IServiceCollection
Интерфейс используется для построения контейнера инъекции зависимостей. После полной сборки он объединяется сIServiceProvider
экземпляром, который можно использовать для разрешения служб. Вы можете ввестиIServiceProvider
в любой класс. ЭтиIApplicationBuilder
иHttpContext
классы могут предоставить поставщик услуг , а также, с помощью ихApplicationServices
илиRequestServices
свойств , соответственно.IServiceProvider
определяетGetService(Type type)
метод для разрешения службы:Есть также несколько удобных методов расширения, таких как
serviceProvider.GetService<IFooService>()
(добавитьusing
дляMicrosoft.Extensions.DependencyInjection
).Разрешение служб внутри класса запуска
Внедрение зависимостей
Хостинг-провайдер среды выполнения может внедрить определенные сервисы в конструктор
Startup
класса, напримерIConfiguration
,IWebHostEnvironment
(IHostingEnvironment
в версиях до 3.0)ILoggerFactory
иIServiceProvider
. Обратите внимание, что последний является экземпляром, созданным на уровне хостинга, и содержит только основные службы для запуска приложения .ConfigureServices()
Метод не позволяет инъекционным услуги, она только принимаетIServiceCollection
аргумент. Это имеет смысл, потому чтоConfigureServices()
именно здесь вы регистрируете сервисы, необходимые для вашего приложения. Однако вы можете использовать сервисы, добавленные в конструктор запуска, например:Любые услуги, зарегистрированные в,
ConfigureServices()
могут затем быть введены вConfigure()
метод; Вы можете добавить произвольное количество сервисов послеIApplicationBuilder
параметра:Разрешение зависимостей вручную
Если вам необходимо разрешить службы вручную, предпочтительно использовать
ApplicationServices
предоставленныйIApplicationBuilder
вConfigure()
методе:Можно передать и напрямую использовать
IServiceProvider
конструктор в вашемStartup
классе, но, как указано выше, он будет содержать ограниченное подмножество сервисов и, следовательно, будет иметь ограниченную полезность:Если вам необходимо разрешить службы в
ConfigureServices()
методе, требуется другой подход. Вы можете создать промежуточное звеноIServiceProvider
изIServiceCollection
экземпляра, который содержит службы, которые были зарегистрированы до этого момента :Обратите внимание: как правило, вам следует избегать разрешения служб внутри
ConfigureServices()
метода, поскольку именно здесь вы настраиваете службы приложения. Иногда вам просто нужен доступ кIOptions<MyOptions>
экземпляру. Вы можете сделать это, связав значения изIConfiguration
экземпляра с экземпляромMyOptions
(что, по сути, и делает инфраструктура опций):Разрешение сервисов вручную (он же Сервисный локатор) обычно считается антишаблоном . Хотя у него есть свои варианты использования (для каркасов и / или инфраструктурных уровней), вы должны избегать его в максимально возможной степени.
источник
IServiceCollection
то класс, который создается вручную ( из области промежуточного программного обеспечения ), в моем случае - планировщик, которому периодически нужны некоторые службы для генерации и отправьте электронное письмо.ConfigureServices
и эта служба является одноэлементной, она будет отличаться от той, которая используется вамиController
! Я предполагаю , что это потому , что она использует другуюIServiceProvider
- чтобы избежать этого не разрешает черезBuildServiceProvider
и вместо того, чтобы переместить поиск в одноэлементном отConfigureServices
кConfigure(..other params, IServiceProvider serviceProvider)
вStartup.cs
IServiceProvider
экземпляр, он создаст новый экземпляр Singleton. Вы можете избежать этого, возвращая экземпляр поставщика услуг изConfigureServices
метода, чтобы он также был контейнером, используемым вашим приложением.collection.BuildServiceProvider();
было то , что мне было нужно, спасибо!Разрешение экземпляров вручную включает использование
IServiceProvider
интерфейса:Разрешение зависимости в Startup.ConfigureServices
Разрешение зависимостей в Startup.Configure
Устранение зависимостей в Startup.Configure в ASP.NET Core 3
Использование Runtime Injected Services
Некоторые типы могут быть введены как параметры метода:
Разрешение зависимостей в действиях контроллера
источник
GetService
который является универсальным, является методом расширения вMicrosoft.Extensions.DependencyInjection
пространстве имен.Если вы создадите приложение с шаблоном, у вас будет что-то вроде этого в
Startup
классе:Затем вы можете добавить зависимости, например:
Если вы хотите получить доступ
ITestService
к вашему контроллеру, вы можете добавитьIServiceProvider
конструктор, и он будет добавлен :Затем вы можете разрешить добавленную вами услугу:
Обратите внимание, что для использования универсальной версии вы должны включить пространство имен в расширения:
ITestService.cs
TestService.cs
Startup.cs (ConfigureServices)
HomeController.cs
источник
Если вам просто нужно разрешить одну зависимость с целью передачи ее конструктору другой зависимости, которую вы регистрируете, вы можете сделать это.
Допустим, у вас есть сервис, который принимает строку и ISomeService.
Когда вы зарегистрируетесь в Startup.cs, вам нужно будет сделать следующее:
источник
ISomeService
для меня все равно было пустым.Таким способом вы можете внедрить зависимости в такие атрибуты, как AuthorizeAttribute.
источник
Я знаю, что это старый вопрос, но я удивлен, что здесь нет довольно очевидного и отвратительного взлома.
Вы можете использовать возможность определения своей собственной функции ctor для извлечения необходимых значений из ваших служб по мере их определения ... очевидно, это будет выполняться каждый раз, когда запрашивается служба, если вы явно не удалите / очистите и не добавите заново определение эта услуга в рамках первой конструкции эксплуатирующего ctor .
Преимущество этого метода заключается в том, что вам не требуется создавать дерево служб или использовать его во время настройки службы. Вы все еще определяете, как будут настроены сервисы.
Способ исправления этого паттерна состоял бы в том, чтобы дать
OtherService
явную зависимостьIServiceINeedToUse
, а не либо неявно зависеть от него или возвращаемого значения его метода ... или явно разрешить эту зависимость каким-либо другим способом.источник
источник