对类的支持

对类的支持

InversifyJS 允许类对其他类的直接依赖。这样做时,您需要使用装饰器 @injectable,但不需要使用装饰器 @inject

使用类作为服务标识时不需要 @inject 装饰器。因为编译器能为我们生成的元数据。但是别忘记下面的配置:

  • 导入 reflect-metadata
  • tsconfig.json 文件中设置 emitDecoratorMetadata 为 true
 1import { Container, injectable, inject } from "inversify";
 2
 3@injectable()
 4class Katana {
 5    public hit() {
 6        return "cut!";
 7    }
 8}
 9
10@injectable()
11class Shuriken {
12    public throw() {
13        return "hit!";
14    }
15}
16
17@injectable()
18class Ninja implements Ninja {
19
20    private _katana: Katana;
21    private _shuriken: Shuriken;
22
23    public constructor(katana: Katana, shuriken: Shuriken) {
24        this._katana = katana;
25        this._shuriken = shuriken;
26    }
27
28    public fight() { return this._katana.hit(); };
29    public sneak() { return this._shuriken.throw(); };
30
31}
32
33var container = new Container();
34container.bind<Ninja>(Ninja).to(Ninja);
35container.bind<Katana>(Katana).to(Katana);
36container.bind<Shuriken>(Shuriken).to(Shuriken);

具体类型绑定自身

如果要解析的类型是具体类型,绑定注册会感到重复和冗长:

1container.bind<Samurai>(Samurai).to(Samurai);

更好的解决方式是使用 toSelf 方法:

1container.bind<Samurai>(Samurai).toSelf();

已知局限性: 类作为标识符和循环依赖

如果在循环依赖中使用类作为标识符会被抛出异常:

Error: Missing required @Inject or @multiinject annotation in: argument 0 in class Dom.

例子:

 1import "reflect-metadata";
 2import { Container, injectable } from "inversify";
 3import getDecorators from "inversify-inject-decorators";
 4
 5let container = new Container();
 6let { lazyInject } = getDecorators(container);
 7
 8@injectable()
 9class Dom {
10    public domUi: DomUi;
11    constructor (domUi: DomUi) {
12        this.domUi = domUi;
13    }
14}
15
16@injectable()
17class DomUi {
18    @lazyInject(Dom) public dom: Dom;
19}
20
21@injectable()
22class Test {
23    constructor(dom: Dom) {
24        console.log(dom);
25    }
26}
27
28container.bind<Dom>(Dom).toSelf().inSingletonScope();
29container.bind<DomUi>(DomUi).toSelf().inSingletonScope();
30const dom = container.resolve(Test); // Error!

这个错误可能有点误导,因为当使用类作为服务标识,@inject 等注解不需要使用,如果我们添加 @inject(Dom)@inject(DomUi) 的注解,依然会抛出相同的异常。因为装饰器被调用的时候,类还没有被声明,所以装饰器被调用为 @inject(undefined),导致 InversifyJS 认为对应的注解没有被添加。

解决办法是使用 Symbol,比如 Symbol.for("Dom") 作为服务标识而不是 Dom 这样的类 :