I've started using Ninject in an ASP.NET MVC 3 project, using the standard boot strapper that comes with the nuget package, as below.
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// Documentation for setting up Ninject in ASP.NET MVC3 app:
// https://github.com/ninject/ninject.web.mvc/wiki/Setting-up-an-MVC3-application
// Add bindings here. No modules required unless we need to add in further
// separation of concerns.
kernel.Bind<ISessionManager>().To<SessionManager>();
kernel.Bind<ICookieManager>().To<CookieManager>();
kernel.Bind<ILogManager>().To<LogManager>();
kernel.Bind<IStringOutput>().To<StringOutput>();
}
Within my Domain Model layer, there is a class called CookieManager
. Within my CookieManager
class, I'm using a class called SecureObjectSerializer
.
I want to use dependency injection so that the CookieManager
is not tighly bound to the SecureObjectSerializer
.
I don't want the MVC project to have to know about the SecureObjectSerializer, setting up the bindings etc. That seems to be taking DI too far to me.
I do however, think that within the Domain Model layer, the CookieManager should have SecureObjectSerializer passed in in a DI manner.
My questions:
To have the binding registered in the Domain Model layer, should I create a Ninject bootstrapper within the Domain Model layer? If so, how should I have this triggered. Would I supply a hook and call something like DomainModel.BindModelDependencies(kernel);
in the MVC project.
When it's time to resolve a new instance of an object, what would this code look like? It's kind of hidden when using the MVC bootstrapper?
You should put a NinjectModule inside of the domain assembly (not the web assembly) and you can tell ninject to scan your domain assembly and look for the module. module is just a class that inherits from NinjectModule base class and implements Load(). This way the web project only needs a reference to the domain project. the Scanning should look something like:
either of these two: (actually there are a few more options but these are the main ones i use)
var assemblysToScan = "Assembly.*";
var assemblysToScan = new[] { "Assembly.Domain", "Assembly.Web" };
and then just
kernel.Scan(x =>
{
x.From(assemblysToScan)
x.AutoLoadModules();
});
When you want to resolve an object, just put it as a ctor argument, and if ninject is managing you objects, it will inject the type (based on the bindings you have configured) automatically.
EDIT:
add references to ninjectcommonservicelocator (cant remember the exact name) & microsoft.practices.servicelocation
in your bootstrapper add these:
using Microsoft.Practices.ServiceLocation;
using CommonServiceLocator.NinjectAdapter;
var locator = new NinjectServiceLocator(kernel);
ServiceLocator.SetLocatorProvider(() => locator);
then in your class:
using Microsoft.Practices.ServiceLocation;
class CookieManager : ICookieManager
{
SecureObjectSerialiser secureObjectSerialiser;
CookieManager()
{
this.secureObjectSerialiser = ServiceLocator.Current.GetInstance<SecureObjectSerialiser>();
}
}
the reason for the microsoft.practices locator is your code should not know that ninject is working under the covers. instead, you use a generic servicelocator that can be reused if you change containers.
personally i would avoid this and just inject everything. but if you cant, you cant.
The accepted answer refers to the Scan()
method from Ninject.Extensions.Conventions
. Ninject 3.0 replaced this with a more powerful fluent interface for doing dynamic assembly binding.
kernel.Bind(x => x
.FromAssembliesMatching("*")
.SelectAllClasses()
.BindDefaultInterface());
The adventure continues at the extension's Wiki.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With