← Все гайды

C# / .NET

DI и scopes в ASP.NET Core: вопросы на собеседовании .NET

Dependency Injection в ASP.NET Core на собесе: Singleton vs Scoped vs Transient, captive dependency, IServiceProvider, типичные ошибки Middle/Senior и как отвечать на system design вокруг DI.

Зачем 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: DbContextScoped. Никогда 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.*