views:

119

answers:

1

I have the following code in my Global.aspx

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}

protected override IKernel CreateKernel()
{
    return new StandardKernel(new ServiceModule());
}

I also have the following Ninject Module:

internal class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IProductService>().To<ProductService>().InRequestScope();
    }
}

I also have a base controller:

public class BaseController : Controller
{
    [Inject]
    public IProductService ProductService
    {
        get;
        set;
    }
}

This code works. The problem I am having is that I would like to remove the inject attribute from the base controller and specify this in the Ninject ServiceModule instead. I other words, how would I go about writing a binding rule in the ServiceModule that tells Ninject to inject ProductService into the property in the base controller?

If I remove the attribute I will get a NullReferenceException.

A: 

Convention-based binding lives in http://github.com/ninject/ninject.extensions.conventions -- one implements IBindingGenerator. This is largely concerned with discovering interfaces and services though.

In general, constructor injection is a good default approach. However the manner in which ASP.NET MVC works makes this harder to do (Hence FubuMVC etc.). So property injection is the next best option.

You may find that using OnActivation in your Bind may allow you to do enough - and if you can, this is by far the simplest.

I'd characterise what you're trying to do as convention-based activation. The problem's are: - deciding what your're going to auto-inject. Are you going to inject everything public that isnt concrete? Everything that your Kernel knows about? Unless you can come up with a clean definition of what you want to do, the injection process can become unpredictable and difficult to understand. You end up debugging and explaining to colleagues a lot. - making it efficient. Ninject dynamically generates code behind the scenes to make the activation of an instance efficient (i.e., at the time of walking the class looking for [Inject] markers it generates code to do that that gets jitted.

Looking in the code, there's no easy way OOTB. Looks like adding a custom IInjectionHeuristic would do the trick.

However if you're getting this deep into containers, you need to

  1. pause and see if you can keep it simple by not going down this road
  2. go to the ninject mailing list and search for similar things
  3. if you still want to do it, send a mail there.
Ruben Bartelink
Ruben, can you provide and example how I would go about writing a binding rule in the ServiceModule that tells Ninject to inject ProductService into the property in the base controller? Thanks!
Thomas
@Thomas: I've never done a customisation of that nature (and as I dont believe it's a good approach have no desire to), I unfortunately wont be able to make the time to do so - sorry... (And as my answer seems to have been judged to be value-less so far, why would I - it's not like I have any feedback that my answer has been understood or is correct?)
Ruben Bartelink