fontcolor_theme
Deepkit Injector

はじめに

Deepkit における Dependency Injection はランタイムタイプに基づいているため、ランタイムタイプが正しくインストールされている必要があります。 ランタイムタイプ を参照してください。

これが成功していれば、@deepkit/injector をインストールするか、すでに内部でこのライブラリを使用している Deepkit フレームワークを使うことができます。

npm install @deepkit/injector

ライブラリがインストールされると、その API を直接使用できます。

使い方

Dependency Injection を使用する方法は 3 つあります。

  • Injector API(低レベル)
  • Module API
  • App API(Deepkit フレームワーク)

Deepkit フレームワークなしで @deepkit/injector を使用する場合は、最初の 2 つの方法を推奨します。

Injector API

Injector API はすでに Dependency Injection の紹介 で説明しました。これは、単一の DI コンテナを作成する単一のクラス InjectorContext によって非常にシンプルに使用でき、モジュールを持たないシンプルなアプリケーションに特に適しています。

import { InjectorContext } from '@deepkit/injector';

const injector = InjectorContext.forProviders([
    UserRepository,
    HttpClient,
]);

const repository = injector.get(UserRepository);

この場合の injector オブジェクトは Dependency Injection コンテナです。InjectorContext.forProviders 関数はプロバイダーの配列を受け取ります。どの値を渡せるかについては、Dependency Injection のプロバイダー の章を参照してください。

Module API

より複雑な API は InjectorModule クラスで、プロバイダーを複数のモジュールに分けて保持し、モジュールごとにカプセル化された複数の DI コンテナを作成できます。さらに、モジュールごとに設定クラスを使用でき、プロバイダーに渡す設定値を自動検証したうえで提供しやすくなります。モジュールは相互にインポートでき、プロバイダーをエクスポートして、階層を構築し、きれいに分離されたアーキテクチャを実現できます。

アプリケーションがより複雑で、Deepkit フレームワークを使用しない場合は、この API を使用すべきです。

import { InjectorModule, InjectorContext } from '@deepkit/injector';

const lowLevelModule = new InjectorModule([HttpClient])
     .addExport(HttpClient);

const rootModule = new InjectorModule([UserRepository])
     .addImport(lowLevelModule);

const injector = new InjectorContext(rootModule);

この場合の injector オブジェクトは Dependency Injection コンテナです。プロバイダーは複数のモジュールに分割でき、モジュールの import を使って別の場所から再度インポートできます。これにより、アプリケーションやアーキテクチャの階層を反映した自然な階層が構築されます。 InjectorContext には常に階層の最上位のモジュール(root モジュールまたは app モジュール)を渡すべきです。InjectorContext は仲介の役割のみを持ち、injector.get() への呼び出しは単に root モジュールへ転送されます。ただし、第二引数としてモジュールを渡すことで、非 root モジュールからプロバイダーを取得することも可能です。

const repository = injector.get(UserRepository);

const httpClient = injector.get(HttpClient, lowLevelModule);

すべての非 root モジュールはデフォルトでカプセル化されており、そのモジュール内のすべてのプロバイダーはそのモジュール自身からのみ利用可能です。プロバイダーを他のモジュールから利用可能にするには、そのプロバイダーをエクスポートする必要があります。エクスポートにより、そのプロバイダーは階層の親モジュールへと移動し、その形で利用できるようになります。

すべてのプロバイダーをデフォルトで最上位(root モジュール)へエクスポートするには、forRoot オプションを使用できます。これにより、すべてのプロバイダーを他のすべてのモジュールから使用できるようになります。

const lowLevelModule = new InjectorModule([HttpClient])
     .forRoot(); // すべてのプロバイダーを root にエクスポート

App API

Deepkit フレームワークを使用する場合、モジュールは @deepkit/app API で定義します。これは Module API を基盤としており、その機能も利用できます。さらに、強力なフックを用いて処理したり、より動的なアーキテクチャを実現するための設定ローダーを定義したりできます。

フレームワークのモジュール の章で詳しく説明しています。

import { App } from '@deepkit/app';
import { FrameworkModule } from '@deepkit/framework';
import { HttpRouterRegistry, HttpBody } from '@deepkit/http';

interface User {
    username: string;
}

class Service {
    users: User[] = [];
}

const app = new App({
    providers: [Service],
    imports: [new FrameworkModule()],
});

const router = app.get(HttpRouterRegistry);

router.post('/users', (body: HttpBody<User>, service: Service) => {
    service.users.push(body);
});

router.get('/users', (service: Service): Users => {
    return service.users;
});
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)