Зачем DI на .NET-собесе — не «для галочки»
В ASP.NET Core backend DI — везде: контроллеры, middleware, background services, тесты. На собесе в продуктовых командах часто спрашивают не «что такое DI», а lifetime scopes и что сломается в production.
Особенно в fintech и highload: неправильный scope → утечки памяти, DbContext на весь процесс, гонки в Singleton.
Три lifetime: запомнить одной фразой
- Transient — создаётся при каждом resolve; лёгкие stateless-сервисы.
- Scoped — на один HTTP-запрос (scope); DbContext, Unit of Work.
- Singleton — один на приложение; кэш конфигурации, HttpClientFactory.
Правило ASP.NET Core: DbContext — Scoped. Никогда Singleton (кроме специальных factory-паттернов, которые вы должны объяснить).
Captive dependency — любимый вопрос интервьюера
Captive dependency: Singleton держит ссылку на Scoped-сервис.
Пример ошибки: Singleton-сервис CacheWarmup принимает DbContext (Scoped) в конструктор — утечка и гонки.
Как исправить: IServiceScopeFactory — создавать scope внутри фоновой работы, не инжектить Scoped в Singleton напрямую.
На собесе произнесите: «Singleton живёт дольше scope — Scoped-сервис в конструкторе Singleton = captive dependency».
IServiceProvider и CreateScope
- В HTTP-запросе scope создаёт middleware автоматически.
- В
BackgroundService— явныйusing var scope = _scopeFactory.CreateScope(). IServiceProvider.GetService<T>()vs constructor injection — «constructor injection предпочтительнее, GetService для optional/factory».
Типовые вопросы
Чем отличается AddSingleton от AddScoped?
Время жизни и потокобезопасность: Singleton должен быть thread-safe или immutable.
Можно ли инжектить Scoped в Controller?
Да — контроллер scoped на запрос.
Как тестировать с DI?
WebApplicationFactory, подмена сервисов в ConfigureTestServices, mock репозиториев.
Keyed services (.NET 8+)
Когда несколько реализаций одного интерфейса — AddKeyedScoped, [FromKeyedServices("redis")].
Связь с архитектурой
На Senior могут спросить: «Как бы вы организовали слои — Domain, Application, Infrastructure?»
Краткий ответ: Domain без DI-атрибутов, Application — интерфейсы use case, Infrastructure — регистрация EF, bus, external API в Program.cs / extension methods.
Подготовка
1. Нарисовать lifetime diagram для одного HTTP-запроса: Middleware → Controller → DbContext.
2. Найти в pet-проекте один BackgroundService с правильным scope.
3. Mock с разбором captive dependency — чеклист mock.
Связанные материалы
---
*Разбор DI и архитектуры на mock-собесе — excalib.ru.*