11

If I have a class with a ctor set up for multi-injection like this:

public Shogun(IEnumerable<IWeapon> allWeapons)
{
    this.allWeapons = allWeapons;
}

And bindings set up like this:

Bind<IWeapon>().To<Sword>();
Bind<IWeapon>().To<Dagger>().WhenInjectedInto<Shogun>();

Then I would expect Shogun to be constructed with both weapons injected? But this isn't the case - it only gets the Dagger.

If I add a further binding like this:

Bind<IWeapon>().To<Sword>();
Bind<IWeapon>().To<Dagger>().WhenInjectedInto<Shogun>();
Bind<IWeapon>().To<Shuriken>().WhenInjectedInto<Shogun>();

Then Shogun gets the Dagger and the Shuriken. WhenInjectedInto<T>() looks like it should only be constraining the binding it is applied to and not affecting other bindings. I find this behaviour very misleading.

Can someone explain what is happening here?

James World
  • 29,019
  • 9
  • 86
  • 120
  • I am sorry, but why would you expect Shogun (in the first case) to be constructed with both weapons injected, when you explicitly are asking to bind IWeapon to Dagger, when injected into Shogun? – virtualmic Sep 04 '11 at 07:57
  • Because I have also asked for `IWeapon` to be bound to `Sword`. Why should binding `IWeapon` to `Dagger` in the specific case prevent the general binding? This means I can write code that makes a specific binding and break more general bindings made elsewhere. It seems dangerous and counter-intuitive. – James World Sep 04 '11 at 08:04
  • 1
    But that would beat the purpose of `WhenInjectedInto`, wouldn't it? I am new to ninject, but as far as I understand, the purpose of this feature is to have specific cases, as you have mentioned, handled. You want `IWeapon` to be bound to `Sword` in general; however, when injected into `Shogun`, you want it to be bound to `Dagger`. If you want `Shogun` to have both `Sword` and `Dagger` injected, `WhenInjectedInto` shouldn't be used, IMHO. – virtualmic Sep 04 '11 at 08:13
  • While we are in the business of disclaimers, I also am new to Ninject. :) I see what you are saying, and it may just be a matter of opinion - I think the reading of WhenInjectedInto is a little ambigious. I was reading it as refering to the implementation (i.e. `Dagger` or `Sword`) rather than the contract (i.e. `IWeapon`), rather than saying "When injecting IWeapon into Shogun inject a Dagger". Read this way it makes sense. – James World Sep 04 '11 at 08:37
  • I still don't like the way the general bindings are then dropped though. :) I can't help but see it potentially breaking things in an unexpected manner in complex applications. – James World Sep 04 '11 at 08:43
  • So, should I post my comment as an answer, then? :) – virtualmic Sep 04 '11 at 08:54
  • I think I'd like to see an answer that explained the mechanics of what is happening in concrete terms. I notice that other When conditions can be applied that seem to combine quite happily with the ones I already have e.g: `Bind().To().When(x => true);` This doesn't mention `Shogun` at all yet still turns up in the multi-injection when `Sword` does not. – James World Sep 04 '11 at 10:59

1 Answers1

13

That's a bug - GetAll will not return all instances in case conditional and unconditional bindings are mixed.

It's fixed in version Version 2.4.0.0

Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98