fontcolor_theme
Deepkit Injector

入门

由于 Deepkit 中的依赖注入基于运行时类型(Runtime Types),因此需要先正确安装运行时类型。参见 运行时类型

一旦完成,便可安装 @deepkit/injector,或者安装已在内部使用该库的 Deepkit 框架。

npm install @deepkit/injector

安装完成后,即可直接使用其 API。

用法

现在使用依赖注入有三种方式。

  • 注入器 API(底层)
  • 模块 API
  • 应用 API(Deepkit 框架)

如果在不使用 Deepkit 框架的情况下使用 @deepkit/injector,推荐前两种方式。

注入器 API

注入器 API 已在依赖注入简介中介绍。其特点是通过单个类 InjectorContext 简单使用,创建一个 DI 容器,特别适合无模块的简单应用。

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

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

const repository = injector.get(UserRepository);

在此情况下,injector 对象即为依赖注入容器。函数 InjectorContext.forProviders 接受一个提供者数组。参见依赖注入提供者了解可传递的值。

模块 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 对象即为依赖注入容器。提供者可以拆分到不同模块中,并通过模块导入在不同位置再次引入。这样就会形成一个自然的层次结构,反映应用或架构的层级。 应始终将层级中的顶层模块(也称根模块或应用模块)传给 InjectorContext。此时 InjectorContext 仅充当中间角色:对 injector.get() 的调用会被简单地转发到根模块。不过,也可以通过将模块作为第二个参数传入,从非根模块获取提供者。

const repository = injector.get(UserRepository);

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

所有非根模块默认都是封装的,因此该模块中的所有提供者仅对自身可用。若希望某个提供者可供其他模块使用,必须将其导出。导出后,该提供者会提升到层级中的父模块,从而以这种方式被使用。

若要默认将所有提供者导出到顶层(根模块),可使用 forRoot 选项。这样所有提供者即可被其他模块使用。

const lowLevelModule = new InjectorModule([HttpClient])
     .forRoot(); //将所有提供者导出到根模块

应用 API

一旦使用 Deepkit 框架,模块将通过 @deepkit/app API 定义。它基于模块 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)