Ответ
IoC-контейнер ASP.NET Core управляет временем жизни зарегистрированных сервисов через три основных варианта, которые критически важны для корректной работы приложения, особенно в веб-сценариях:
-
Transient (Временный)
- Поведение: Контейнер создаёт новый экземпляр каждый раз, когда сервис запрашивается (каждый вызов
GetServiceили внедрение через конструктор). - Использование: Для лёгких, не имеющих состояния (stateless) сервисов, где каждый вызов должен быть изолирован. Например, простые валидаторы, преобразователи данных.
services.AddTransient<IEmailValidator, EmailValidator>();
- Поведение: Контейнер создаёт новый экземпляр каждый раз, когда сервис запрашивается (каждый вызов
-
Scoped (В рамках области)
- Поведение: В рамках одной области (scope) используется один и тот же экземпляр. В веб-приложении новая область создаётся автоматически для каждого HTTP-запроса. Это самый часто используемый вариант.
- Использование: Для сервисов, которые должны сохранять своё состояние в рамках одного запроса, например,
DbContextв Entity Framework Core, репозитории, сервисы бизнес-логики.services.AddScoped<IOrderRepository, OrderRepository>();Важно: Попытка разрешить Scoped-сервис из Singleton или вне области видимости приведёт к исключению.
-
Singleton (Одиночка)
- Поведение: Контейнер создаёт один экземпляр при первом запросе и затем возвращает его на протяжении всей жизни приложения.
- Использование: Для сервисов, которые дорого создавать (кэши, клиенты для внешних API с пулом соединений) или должны быть единым источником состояния для всего приложения. Необходимо проектировать такие сервисы как потокобезопасные (thread-safe).
services.AddSingleton<ICacheService, DistributedCacheService>();
Практическое правило: Используйте Scoped по умолчанию для сервисов, работающих с данными запроса. Используйте Transient для простых, не имеющих состояния утилит. Используйте Singleton осознанно, только для сервисов, которые действительно должны существовать в единственном экземпляре.