对类的支持
对类的支持
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 这样的类 :