多重注入

当有两个或者多个具体实现被绑定到同一个抽象时,我们可以使用多重注入。注意 Weapon 数组时怎样通过使用 @multiInject 装饰器从而由构造器注入到 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];
    }
}

我们将 KatanaShuriken 绑定到了 Weapon 中:

container.bind<Ninja>("Ninja").to(Ninja);
container.bind<Weapon>("Weapon").to(Katana);
container.bind<Weapon>("Weapon").to(Shuriken);

关于展开 ... 运算符

在 InversifyJS 的早期发布版本中,展开运算符会失败并且不报错。这是不可接受的,于是我们修复了它,从而允许你使用展开运算符注入数组。但是这并不被推荐,因为实际上没有什么用处。

你可以像下面这样使用 @multiInject...

@injectable()
class Foo {
    public bar: Bar[];
    constructor(@multiInject(BAR) ...args: Bar[][]) {
        // 参数 args 将永远包含唯一一个元素,即 Bar[]
        this.bar = args[0];
    }
}

主要的问题是这需要 args 的类型为 Bar[][],因为 multiInject 会使用数组包装注入项,而展开运算符也是如此。最终结果就是注入项被数组包裹了两次。

我们尝试解决这个问题但是只有一个办法就是使用 @spread() 装饰器生成一些额外的元数据。

@injectable()
class Foo {
    public bar: Bar[];
    constructor(@multiInject(BAR) @spread() ...args: Bar[]) {
        this.bar = args[0];
    }
}

我们放弃了这个想法,因为只有当没有其他办法时再使用装饰器来实现某些事情会更好。在这个情况下明明有一种更加简便的方式达到同样的效果,即使用 @multiInject 并且避免使用 ...

@injectable()
class Foo {
    public bar: Bar[];
    constructor(@multiInject(BAR) args: Bar[]) {
        this.bar = args;
    }
}

results matching ""

    No results matching ""