Внедрение зависимостей в ASP.NET Core
Вопрос
Как работает встроенный DI-контейнер ASP.NET Core и какие ошибки с ним бывают?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Регистрация в IServiceCollection, разрешение через IServiceProvider, внедрение через конструктор
Три времени жизни и правило не зависеть от более короткоживущих
Captive dependency и ValidateScopes
Scope вручную через IServiceScopeFactory в синглтонах и фоновых службах
Освобождение IDisposable контейнером
Service locator как антипаттерн
Что могут спросить следом
- Как получить scoped-сервис в BackgroundService?
- Почему не стоит внедрять IServiceProvider в бизнес-классы?
Разбор
Встроенный контейнер простой: сервисы регистрируются в IServiceCollection с временем жизни, а при создании контроллера или другого сервиса IServiceProvider смотрит на конструктор и рекурсивно создаёт зависимости.
Главное правило: сервис не должен захватывать зависимость с более коротким временем жизни. Если синглтон получит scoped DbContext, тот станет общим для всех запросов. В Development это ловит проверка ValidateScopes. В фоновых службах и синглтонах scoped-сервисы получают через IServiceScopeFactory.CreateScope() на каждую единицу работы.
Контейнер сам вызывает Dispose у созданных им объектов при закрытии scope, поэтому вручную освобождать внедрённые сервисы не нужно. Чего избегаю: внедрять IServiceProvider и вытаскивать зависимости по месту. Это service locator, зависимости становятся неявными, а тесты сложнее. Для нескольких реализаций одного интерфейса использую IEnumerable<T> или keyed services из .NET 8.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.