2
votes

I'M just trying to get started with Ninject 2 and ASP.NET MVC 2. I have followed this tutorial http://www.craftyfella.com/2010/02/creating-aspnet-mvc-2-controller.html to create a Controller Factory with Ninject and to bind a first abstract to a concrete implementation. Now I want to load a repository type from another assembly (where my concrete SQL Repositories are located) and I just cant get it to work. Here's my code:

Global.asax.cs

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);


        ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
    }

Controller Factory:

public class Kernelhelper
{
    public static IKernel GetTheKernel()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(System.Reflection.Assembly.Load("MyAssembly"));
        return kernel;
    }
}

public class MyControllerFactory : DefaultControllerFactory
{
    private IKernel kernel = Kernelhelper.GetTheKernel();


    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {

        return controllerType == null ? null : (IController)kernel.Get(controllerType);
    }
}

In "MyAssembly" there is a Module:

    public class ExampleConfigModule : NinjectModule
{
    public override void Load()
    {
        Bind<Domain.CommunityUserRepository>().To<SQLCommunityUserRepository>();
    }

}

Now when I just slap in a MockRepository object in my entry point it works just fine, the controller, which needs the repository, works fine. The kernel.Load(System.Reflection.Assembly.Load("MyAssembly")); also does its job and registers the module but as soon as I call on the controller which needs the repository I get an ActivationException from Ninject:

No matching bindings are available, and the type is not self-bindable. Activation path: 2) Injection of dependency CommunityUserRepository into parameter _rep of constructor of type AccountController 1) Request for AccountController

Can anyone give me a best practice example for binding types from external assemblies (which really is an important aspect of Dependency Injection)? Thank you!

1
Stupid me, the constructor of my concrete implementation requires a connection string. Now I have to find out how to tell that to Ninject...hoetz

1 Answers

0
votes

Ok, I did some refactoring and now I got it running. I'll post the code of my Global.asax since that's where everything happens. I'm using the latest Ninject 2 Build with the latest Ninject.Web.Mvc Build for MVC 2.

 public class MvcApplication : NinjectHttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );

    }

    protected override void OnApplicationStarted()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        RegisterAllControllersIn(System.Reflection.Assembly.GetExecutingAssembly());
    }


    protected override Ninject.IKernel CreateKernel()
    {

        var kernel = new StandardKernel();
        kernel.Load(new ExampleConfigModule());
        return kernel;
    }
}

public class ExampleConfigModule : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        string connectionString =
            ConfigurationManager.ConnectionStrings
            ["ConnectionString1"].ConnectionString;
        string communityUserRepTypeName =
           ConfigurationManager.AppSettings
           ["CommunityUserRepositoryType"];
        var communityUserRepositoryType =
            Type.GetType(communityUserRepTypeName, true);
        Bind<Domain.CommunityUserRepository>().To(communityUserRepositoryType).WithConstructorArgument("conString",connectionString);
    }

}

As you can see I got rid of my ControllerFactory, inherited from NinjectHttpApplication and load & bind the external assemblies' type in the Module. Now there might be a better way without specifiyng the type as a string in the config file, maybe you could declare the Module in the external assembly and let Ninject auto-load it from there but I still would need to pass the connection string down to the constructor of the concrete implementation. Maybe someone got an idea for this but for now this works fine.