多重注入
当有两个以上的具体类型绑定了一个抽象时,我们可以使用多重注入(multi-injection)。多亏有@multiInject
装饰器,我们才能够将Weapon
数组通过Ninja
类的构造器进行注入:
interface Weapon {
name: string;
}
@injectable()
class Katana implements Weapon {
public name = "Katana";
}
@injectable()
class Shuriken implements Weapon {
public name = "Shuriken";
}
interface Ninja {
katana: Weapon;
shuriken: Weapon;
}
@injectable()
class Ninja implements Ninja {
public katana: Weapon;
public shuriken: Weapon;
public constructor(
@multiInject("Weapon") weapons: Weapon[]
) {
this.katana = weapons[0];
this.shuriken = weapons[1];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
我们将Katana
和Shuriken
绑定到Weapon
:
container.bind<Ninja>("Ninja").to(Ninja);
container.bind<Weapon>("Weapon").to(Katana);
container.bind<Weapon>("Weapon").to(Shuriken);
1
2
3
2
3
关于扩展运算符(...)
在InversifyJS的早期版本中,扩展运算符(...)通常会不起作用而且不会抛出任何错误。这显然是我们无法接受的,因此开发组做出了修复,允许您使用扩展运算符注入数组。但我们并不推荐这么做,因为它看起来没什么用。
您可以像下面这样使用@multiInject
和...
:
@injectable()
class Foo {
public bar: Bar[];
constructor(@multiInject(BAR) ...args: Bar[][]) {
// args will always contain one unique item the value of that item is a Bar[]
this.bar = args[0];
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
这里有一个问题,args
的类型被定义为Bar[][]
,这是因为multiInject
会将注入项使用数组进行包裹而扩展运算符也会这么做。其结果就是注入项被数组包裹了两层。
我们尝试过解决这个问题,可惜的是唯一的解决办法是通过@spread()
装饰器生成一些额外的元数据。
@injectable()
class Foo {
public bar: Bar[];
constructor(@multiInject(BAR) @spread() ...args: Bar[]) {
this.bar = args[0];
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
于是我们放弃了这个想法。基于没有其他方法可以实现某些功能时最好使用装饰器的思想,我们只使用@multiInject
而不使用...
其实就能够达成预期效果了,这么做反而更简单。
@injectable()
class Foo {
public bar: Bar[];
constructor(@multiInject(BAR) args: Bar[]) {
this.bar = args;
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7