3
votes

I have a .Net 4.0 WCF service that I'm trying to setup ninject for. I downloaded the WCF extension for ninject and had a look through the TimeService example. Everything looks simple enough, however I can't see how ninject is doing its job correctly as there is a parameter-less constructor manually injecting the dependency.

 public TimeService()
    : this(new SystemClock())
{
}

public TimeService( ISystemClock systemClock )
{
    _systemClock = systemClock;
}

As far as I understand this code will never use ninject binding. The first constructor will call the second constructor if I don't provide any params. When in testing and I pass in my mock object the second constructor will be called. I'm pretty new to both WCF and ninject so apologies if I am missing anything obvious!

Can anyone explain?

Thanks

1

1 Answers

2
votes

By default, Ninject will choose the constructor that has the largest number of parameters, which it has enough binding information to fill. So if the Ninject module is capable of providing an ISystemClock implementation, Ninject will prefer the second constructor.

The pattern you're showing here is often used when you want to allow for injected dependencies, but still have a logical default to fall back on in the absence of a specific dependency. As you pointed out, you can provide your own ISystemClock mock when unit testing, which gives you the advantage of deterministic testing. Likewise, if you had some reason to want to provide a custom ISystemClock implementation, you could set up your Ninject modules with a matching binding.

On the other hand, for most purposes the stock SystemClock implementation is probably the best one to use, so rather than forcing you to set up an ISystemClock binding in order for the class to even function, an alternate constructor is provided which uses the SystemClock as a default implementation. Ninject will fall back on this constructor if you haven't specified a binding for the ISystemClock service.

Edit

In this particular case, the reason it's not running is due to the following attribute on the TimeService class:

[ServiceBehavior( InstanceContextMode = InstanceContextMode.Single )]

I don't fully understand what all is going on here, but it is somehow preventing Ninject from being used to create the service. If you comment out this line, it should work as expected.