Skip to content

Контроль времени жизни

В InferDI есть три вида времени жизни:

ВидСозданиеКешОчистка
singletonодин раз на контейнер-владелецконтейнер-владелецда
scopedодин раз на дочерний scopeдочерний scopeда
transientпри каждом resolveникогданет

При strict: true попытка получить scoped-ключ из root выбрасывает Scoped "key" cannot be resolved from the root container. Use createScope(). Получайте scoped-сервисы из дочернего контейнера, который вернул createScope().

Правило жизненного цикла

Singleton не может напрямую зависеть от scoped или transient сервиса. Singleton создаётся один раз и разделяется между всеми запросами, поэтому если он захватит scoped-значение - контекст текущего запроса, пользователя или транзакцию - состояние одного запроса незаметно протечёт во все остальные. InferDI делает такую связь невыразимой в системе типов, а не оставляет её на code review.

ts
new Container()
  .registerClass('request', RequestContext, [], 'scoped')
  .registerClass('users', UserService, ['request'], 'singleton')

Такую регистрацию отклонит TypeScript. В strict mode та же форма будет отклонена runtime-защитой, если каст обойдёт систему типов.

Строгий режим

strict: true включен по умолчанию. Он ловит:

  • прямой resolve scoped-ключа из root-контейнера
  • нарушения singleton-to-scoped и singleton-to-transient через касты
  • утечки из фабрик, которые захватили внешний контейнер
  • синхронные singleton-циклы
  • синхронные transient-циклы
  • неправильное использование динамических ключей, обходящее статическую проверку
ts
const root = new Container({ strict: true })

Быстрый режим

Используйте strict: false только после того, как тесты доказывают форму графа:

ts
const root = new Container({ strict: false })

Быстрый режим убирает runtime-учёт циклов и времени жизни из пути resolve. Scope читает неизменяемый root registry напрямую, не проходя цепочку родителей, а delegated singleton зеркалируется в cache scope. Strict scope при каждом локальном промахе проходит точную цепочку родителей, поэтому мутации остаются видимыми без сохранённых метаданных lookup. Дедупликация owned-инстансов выполняется во время disposal в обоих режимах. Контракт на уровне типов не меняется, но Fast Mode не защищает от нечестных кастов, захваченных внешних контейнеров и циклов. Он также отключает запрет на resolve scoped-ключей из root, поэтому код приложения не должен обращаться к ним через root-контейнер.

Рекомендуемый процесс: разрабатывать и тестировать в strict mode, регистрировать каждый runtime-ключ один раз в одной линейной fluent-цепочке и завершить регистрацию до первого resolve или создания scope. Переключайте только проверенные неизменяемые production-графы и закрывайте дочерние scope раньше предков.