Каково время жизни объекта при его добавлении в DI-контейнер в ASP.NET Core?

«Каково время жизни объекта при его добавлении в DI-контейнер в ASP.NET Core?» — вопрос из категории ASP.NET Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Время жизни (lifetime) объекта в DI-контейнере ASP.NET Core определяется при регистрации сервиса и влияет на то, как часто создается новый экземпляр.

Существует три основных варианта:

  1. Transient (Временный) – новый экземпляр создается каждый раз, когда сервис запрашивается из контейнера. Подходит для легковесных, stateless-сервисов.
    services.AddTransient<IMyService, MyService>();
  2. Scoped (В рамках области) – один экземпляр создается на одну область (scope). В веб-приложении область по умолчанию — это один HTTP-запрос. Это самый частый выбор для сервисов, работающих с контекстом запроса (например, DbContext в Entity Framework Core).
    services.AddScoped<IMyRepository, MyRepository>();
  3. Singleton (Одиночка) – один экземпляр создается на все время работы приложения. Используется для сервисов, которые должны быть общими для всех запросов (например, кэш в памяти, логгер, конфигурация).
    services.AddSingleton<IMemoryCache, MemoryCache>();

Критически важные моменты:

  • Несоответствие времен жизни: Сервис с более коротким временем жизни не должен зависеть от сервиса с более долгим. Например, Scoped сервис не может зависеть от Transient сервиса, если этот Transient сервис не был зарегистрирован правильно.
  • Особенности Scoped вне веб-контекста: В консольных приложениях или фоновых задачах область видимости нужно создавать вручную через IServiceScopeFactory.CreateScope().
  • Потокобезопасность: Singleton сервисы должны быть спроектированы как потокобезопасные.
  • Утечки памяти: Singleton, который хранит ссылки на Scoped сервисы или большие данные, может привести к утечке памяти.