スコープとリソース破棄
スコープは、リクエストローカルなサービスのライフタイムを 1 つの作業単位に限定します。子スコープはすべての親の登録を継承しますが、自身のスコープドなインスタンスをキャッシュし、そのクリーンアップを所有します。そのため、あるリクエストのために生成されたスコープが、別のリクエストと状態を共有したり、それより長く存続したりすることはありません。
const root = new Container()
.declareScopeInputs<{ request: RequestContext }>()
.registerClass('db', Db, [])
.registerClass('handler', RequestHandler, ['request', 'db'], 'scoped')
async function handle(request: Request) {
await using scope = root.createScope({ request })
return scope.get('handler').run()
}db はルートの singleton です。request は外部のスコープ入力としてアプリケーションが所有し、handler はリクエストスコープが生成して破棄します。
scoped 登録は子スコープに属します。既定の fast: false でルートから解決すると、Scoped "key" cannot be resolved from the root container. Use createScope(). がスローされます。createScope() が返したコンテナーからキーを解決してください。fast: true はこの実行時ガードを省略します。
スコープ入力
Scope input は、スコープを開くときに存在する外部値を表します。対象には request、認証コンテキスト、tenant、job データなどがあります。先に宣言し、必要な部分を createScope(inputs) で渡します。
const root = new Container()
.declareScopeInputs<{request: RequestContext}>()
.registerClass('service', RequestService, ['request'], 'scoped')
await using scope = root.createScope({request})
scope.get('service')コンテナー型は提供済み input を記録し、準備が整うまで依存サービスを隠します。名前付きプロファイル、nested refinement、依存キー付き factory、再利用型、入力検証の規則はスコープ入力を参照してください。
所有権
所有権は、コンストラクターを呼び出したコードだけでなく、登録方法によって決まります。
| 値 | 所有者とクリーンアップ |
|---|---|
| singleton の factory または class の結果 | 登録を所有するコンテナー |
| scoped の factory または class の結果 | 解決してキャッシュしたスコープ |
| transient の factory または class の結果 | 呼び出し元。InferDI は破棄のために保持しません |
registerValue の値 | アプリケーション |
.override() の値 | アプリケーションまたはテスト fixture |
| スコープ入力 | スコープを開いたコード |
root.dispose() は、すでに生成された子スコープへカスケードしません。スコープはそれぞれのライフサイクルの境界で破棄してください。
ネイティブのリソース管理
Container は両方の破棄シンボルを実装しています:
using syncScope = root.createScope()
await using asyncScope = root.createScope()所有するリソースのいずれかが非同期になりうる場合は、await using または await container.dispose() を使用してください。
破棄のプロトコル
所有するインスタンスは、生成と逆の順序で破棄されます。コンテナは次の順で調べます:
Symbol.asyncDisposeSymbol.dispose.dispose()
複数の破棄処理が失敗した場合、InferDI はそれらを AggregateError にまとめます。これにより、1 つの不正なクリーンアップが、後続のリソースのクローズを妨げることはありません。
