2
votes

I use the nuget template way of ninjectning my MVC3 app, which means I have use WebActivator to invoke a method on a static class that in turn creates a Ninject bootstrapper and hooks up to MVC3.

That works fine for Controller, adapters etc. But I want to have another Webactivator activated class which gets its dependencies using Ninject.

I got it to work with a poor mans solution, but I would prefer a more elegant solution.

First I make sure my Webactivator class uses the PostApplicationStartMethod invoke, since the Ninject module uses the PreApplicationStartMethod I can ensure that ninject has been loaded and is ready to go.. THen in the Start method I do

var workers = DependencyResolver.Current.GetServices<IWorker>();

To get my dependencies, the whole class looks like this

[assembly: WebActivator.PostApplicationStartMethod(typeof(SHB.DALA.Web.App_Start.WorkflowRunner), "Start")]

namespace SHB.DALA.Web.App_Start
{
    public static class WorkflowRunner 
    {
        public static void Start()
        {
            var workers = DependencyResolver.Current.GetServices<IWorker>();
            //Do stuff with worker collection
        }
    }
}

There must be a more elegant solution right?

2

2 Answers

3
votes

WebActivator (ASP.NET really) doesn't have any knowledge of Ninject project and therefore cannot have any parameters injected. You would need a Ninject WebActivator extension (the same way you have a Ninject MVC extension) to achieve it. But frankly this is a bit of a catch-22: you want WebActivator to setup Ninject and at the same time Ninject to setup WebActivator.

I can think of 2 possible scenarios for you:

  1. leave the code as it is - I honestly don't know why you don't like your WorkflowRunner class. It is a nice, small class, no other code has any dependency on it, You obtain your references through a DependencyResolver which abstracts you from Ninject itself, your workflow initialization is nicely encapsulated there. I do not smell anything wrong here, really.

  2. Initialize your workflows in the other WebActivator class, where setup Ninject. You know there that your Ninject is initialized and you can still keep workflow initialization code in a separate class.

I would obviously choose 1. if I were you.

0
votes

If you already have the Ninject bootstrapper working, are you sure you need another solution? For non-controller dependencies, I use a BindingFactory class which has a GetInstance() method. This just calls the Get() method on the Kernel object.

public class BindingFactory
{
    private static readonly IKernel Kernel = new StandardKernel(new DefaultServices());

    public static T GetInstance<T>()
    {
        return Kernel.Get<T>();
    }

    public static IController GetControllerInstance(Type controllerType)
    {
        return Kernel.Get(controllerType) as IController;
    }
}

I then use a NinjectControllerFactory which utilises the BindingFactory.

public class NinjectControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType == null)
            return null;

        return BindingFactory.GetControllerInstance(controllerType);
    }
}

So I'm thinking you could just adapt your current implementation.