15

I am tring to use Ninject as a IoC container but could not understand how to create an instance of a class that has more than 1 parameter in the constructor. Basically I have a service interface for authentication in a PCL library and its implementation in a WP8 project that receives in the constructor the cosumer key, secret and baseAddress:

//On PCL project
public interface IAuthorizationService {
 bool Authenticate();
}

//On WP8 Project
pubilc class MyAuthenticator : IAuthorizationService {
 public MyAuthenticator(string consumerKey, string consumerSecret, string baseAddress) { ... }
 public bool Authenticate() { ... }
}

Now I need to configure Ninject module so I can get an instance of IAuthorizationService. If my class had no constructors I would do:

internal class Module : NinjectModule {
 public override void Load() {
  this.Bind<IAuthorizationService>().To<MyAuthenticator>();
 }
}

If it had fixed values for the constructor I would do:

internal class Module : NinjectModule {
 public override void Load() {
  this.Bind<IAuthorizationService>().To<MyAuthenticator>().WithConstructorArgument( */* fixed argument here*/* );
 }
}

And to get an instance Module.Get<IAuthorizationService>()

But what if the constructor parameters cannot be resolved at compile time? How to pass the paramenters? How should the bind code be?

Edited to claryfy the question.

5
  • Why the downvote? should have at least commented so I could change the question... Commented Sep 4, 2014 at 14:25
  • it's probably because they felt that this question is easily answered by looking at the docs: github.com/ninject/ninject/wiki/… Commented Sep 6, 2014 at 13:34
  • No, it is not! If you look at the docs all the constructor parameters are "injectable" too. My constructor has strings parameters. Commented Sep 8, 2014 at 13:17
  • to be precise, string is just another type which is just as "injectable" as any other type (interface, class). however, due to it's broad use it's not really suitable for injection. The same would be true for an ICurrency or ICultureInfo interface, too. Usually broadly-used types are passed as parameter or retrieved from a factory/provider (which is injected), p.Ex. ICurrencyProvider.GetUsersCurrency() or ICultureInfoProvider.GetCurrentUiCulture(). It quite the same concept as with entities: you usually don't inject an entity, rather you pass it along, or retrieve it from a repository. Commented Sep 8, 2014 at 14:38
  • 3
    I upvoted this because I agree, the docs are garbage because they're tailored to work perfectly to the example they're showing. Concise real-world examples are much more favorable.
    – Brandon
    Commented Jul 30, 2015 at 14:22

2 Answers 2

12

It's very easy. No matter how many constructor arguments, the binding stays the same:

Bind<IAuthorizationService>().To<MyAuthenticator>();

Let's say MyAuthenticator had a constructor with one parameter of type IFoo. All you got to do is tell ninject how it can resolve/create an IFoo. Again, very simple:

Bind<IFoo>().To<Foo>();

You don't need WithConstructorArgument ever, except in case you want to override the default behavior of ninject. Let's say MyAuthenticator has a parameter of type IFoo plus another parameter string seed which you want to configure specifically. All you'd need is:

Bind<IFoo>().To<Foo>();
Bind<IAuthorizationService>().To<MyAuthenticator>()
    .WithConstructorArgument("seed", "initialSeedValue");

no need to specify the value of the IFoo parameter!

4
  • 2
    That is the problem, my constructor has string parameters and I dont know their value on Bind time. Commented Sep 8, 2014 at 13:18
  • Where do you get the values of the string parameters from? I reckon you might need a factory. Why don't you pass these string parameters as argument to the Authenticate() method? Commented Sep 8, 2014 at 14:08
  • 2 of then are from configuration files so I passed then with ´WithConstructorArgument()´ method. The other one depends on user input. Commented Sep 9, 2014 at 12:32
  • Then you would need to consider using a factory (have a look at ninject factory extension). Or otherwise, inject an object which is a "placeholder" for the user input. Bind it .InSingletonScope() and have the UI set the value and after that the AuthorizationService read it.. Commented Sep 10, 2014 at 6:05
2

Ninject can inject more than one constructor arguments like:

 Bind<IMyClass>().To<MyClass>().InSingletonScope()
                .WithConstructorArgument("customerName", "Daenerys Targeryan")
                .WithConstructorArgument("customerAddress", "King's Landing");

It does not change how the binding works.

Not the answer you're looking for? Browse other questions tagged or ask your own question.