5
votes

I'm playing around with Ninject for a simple test-bed project at home, just to see what I can do with it. As a starting point I'm building a console runner for some service, which accepts a variety of arguments and based on what it gets in, uses the same methods provided for a fluent interface to configure a model to run.

As an example, suppose I have a verbosity switch, /o. /o can be passed as /o:quiet, /o:normal, or /o:verbose. The various options are self-explanatory.

To satisfy this argument I would like to attach various implementations of ILogger - quiet gets a quiet logger that prints only critical messages, normal gets a normal logger, and verbose gets a chatty logger that prints everything.

What I'd like to do is something in a module like:

Bind<ILogger>().To<QuietLogger>().When(VerbosityParameter=="quiet");
Bind<ILogger>().To<VerboseLogger>().When(VerbosityParameter=="verbose");

...and so on.

I can't see how to do anything like this; all the conditional bindings seem to be dependent on the state of the injection target. What's the point of that? Doesn't it defeat the entire point of dependency injection when the consuming class has to specify in exact detail all the conditions needed to determine what concrete type it gets given? Why can't I just tell Ninject what I want, and get it?

2
I realize this question is ancient, but I think I ran into a similar issue just recently, and finally got Ninject to (sort of) behave the way I wanted by using ToMethod for binding, and then passing a Ninject Parameter to the kernel's Get. This gave me access to the context along w/ parameter value as I needed. stackoverflow.com/questions/22766200/… - Brett Rossier

2 Answers

4
votes

The ctx parameter is just one input into the contextual binding - there's nothing saying you need to pay the slightest bit of attention to it (except you need to be signature compatible with the delegate signature).

Bear in mind the RRR pattern though and don't go crazy.

IOW you need to be (in V2 syntax doing it):

Bind<IWarrior>().To<Samurai>().When(_ => expression not involving context at all);

(Where _ is a poor man's pidgin use of the F# pattern matching syntax for ignoring inputs)

4
votes

In this special case I wouldn't replace the logger instance but rather configure your logging framework to log exactly what you want to.

Also the When condition does not depend on the target you can put there any kind of condition. E.g.

When(ctx => Configuration.Get("VerborsityLevel") == "quiet")