9

I updated Ninject.MVC3 package from 2.2.1.0 to 2.2.2.0. Before I had access to the Kernel object through BootStrapper.Kernel property but in the new version Kernel property is marked as obsolete. I get a warning saying

'Public ReadOnly Property Kernel As Ninject.IKernel' is obsolete: 'Do not use Ninject as Service Locator'.

Is there a different way to access the kernel in the new version?

mahichR
  • 355
  • 3
  • 14

4 Answers4

6

If you have a class that (for some reason) needs to retrieve objects from the Ninject kernel, you can include the kernel as one of the injected properties/constructor parameters on the class. This pattern is better in the sense that you're explicitly declaring that a particular class is using the kernel, rather than always having it available as the service locator pattern does.

This assumes that Ninject automatically adds an instance binding of the kernel to itself. I know that it used to do this, but if it doesn't you can add the binding manually.

John Bledsoe
  • 17,142
  • 5
  • 42
  • 59
  • Injecting kernel into my classes will require lot of code change and violate my existing application architecture. So this is not and option. Thanks for the suggestion though. – mahichR May 18 '11 at 17:25
  • Can you post some example code that shows how/why injecting IKernel would violate your architecture? – FMM Jul 13 '11 at 15:41
  • I'm of the opinion you should attach your IKernel instance to only classes around object management; definately not to the services or business logic. – Dan Jul 18 '11 at 16:01
  • I need the kernel in a static method, so I can't inject it as a property. Does anyone know a workaround for this case? – ibz Jun 13 '12 at 14:32
  • @ibz That sounds like an anti-pattern in a dependency injected system. You could register your kernel as a service locator and get it that way in your static method. It'll work but isn't clean. – John Bledsoe Jun 13 '12 at 15:55
5

The reason why this has been marked Obsolete and will be changed to internal in future is that people tend to use Ninject as a service locator if it is possible to do so. But Service Locator is an antipattern that should not be used. And as we don't want to provide functionality that helps building badly designed software it will be removed in future.

If this needs a lot of changes in your code this is sign that your code is suffering from this malaise Dependency Injection wise and you really should change it to a better design.

  1. Limit your access to the kernel to a mimimum. There is almost no situation in MVC where you need something other than plain constructor injection. Therefore my first advice is to refactor to constructor injection where possible.
  2. For these very rare cases where you need access to the kernel to create other objects you should inject a factory to the class that needs the new instance and inject the kernel into this factory (if the Constructor has a Kernel parameter, it'll receive the instance doing the injecting).

If you really want to stay with service locator even if almost everyone will tell you not to, you will have to keep a static reference yourself.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • 3
    All my MVC related code for example Controllers have constructor injection so no problem there. But in one situation I have to implement a custom Membership provider where I want to pass IRepository into the ctor. The ony solution I can find is here http://stackoverflow.com/questions/5596441/inject-repository-to-custom-membership-provider-with-ninject . Thats the reason I need access tot he Kernel. Do you know of a better approach? – mahichR May 19 '11 at 12:32
2

In ASP.NET MVC 3, I think DepedencyResolver is a clean way to get a service locator.

Guillaume86
  • 14,341
  • 4
  • 53
  • 53
  • 2
    Getting instances from the DependencyResolver is exactly the same as the ServiceLocator pattern. The only thing it should be used for is to create controller instances and it should only be called by the MVC framework and not by any own code. – Remo Gloor Jul 13 '11 at 15:46
  • Well I've answered to the question and said it was service location (not depedency injection), I don't think I deserve the downvote – Guillaume86 Jul 19 '11 at 19:22
0

You could use the Common Service Locator as a service location hook into Ninject. The Common Service Locator only allows you to retrieve objects though, not inject objects that you already have. Of course you could hack around this restriction, but you could just as easily create a static class that exposes the Ninject kernel and reference that rather than the BootStrapper.

John Bledsoe
  • 17,142
  • 5
  • 42
  • 59