inversify / InversifyJS

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
http://inversify.io/
MIT License
11.16k stars 713 forks source link

multiInject with only one injectable #155

Closed rashtao closed 8 years ago

rashtao commented 8 years ago

What is the multiInject annotation supposed to return? If I have many injectables boud to the kernel, it works as expected, returning them in an array. If I have only one injectable bound, I get just that object (not an array containing it).

Is it a bug? Should it return an array containing exactly one element?

Here is an example:

import { injectable, inject, multiInject, Kernel} from "inversify";

interface IWeapon {
    name: string;
}

@injectable()
class Katana implements IWeapon {
    public name = "Katana";
}

@injectable()
class Shuriken implements IWeapon {
    public name = "Shuriken";
}

interface INinja {
    katana: IWeapon;
    shuriken: IWeapon;
}

@injectable()
class Ninja implements INinja {
    public katana: IWeapon;
    public shuriken: IWeapon;
    public constructor(
        @multiInject("IWeapon") weapons: IWeapon[]
    ) {
        this.katana = weapons[0];
        this.shuriken = weapons[1];
    }
}

@injectable()
class WeaponContainer {
    constructor( @multiInject("IWeapon") public weapons: IWeapon) { };
}

// case with 2 IWeapon
let kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IWeapon>("IWeapon").to(Katana);
kernel.bind<IWeapon>("IWeapon").to(Shuriken);
kernel.bind<WeaponContainer>("WeaponContainer").to(WeaponContainer);

// case with 1 IWeapon
let kernel2 = new Kernel();
kernel2.bind<INinja>("INinja").to(Ninja);
kernel2.bind<IWeapon>("IWeapon").to(Katana);
kernel2.bind<WeaponContainer>("WeaponContainer").to(WeaponContainer);

console.log(kernel.get<WeaponContainer>("WeaponContainer"));
console.log(kernel2.get<WeaponContainer>("WeaponContainer"));

This is the output:

WeaponContainer {
  weapons: [ Katana { name: 'Katana' }, Shuriken { name: 'Shuriken' } ] }
WeaponContainer { weapons: Katana { name: 'Katana' } }
remojansen commented 8 years ago

Yes it looks like a bug. I think if you use the @multiInject decorator the injected value should always be an array (even if there is only one binding). Thanks for spotting this issue.