views:

59

answers:

1

I have the following project layout:

MVC UI
|...CustomerController (ICustomerRepository - how do I instantiate this?)

Data Model
|...ICustomerRepository

DAL (Separate Data access layer, references Data Model to get the IxRepositories)
|...CustomerRepository (inherits ICustomerRepository)

What's the correct way to say ICustomerRepository repository = new CustomerRepository(); when the Controller has no visibility to the DAL project? Or am I doing this completely wrong?

+2  A: 

You could use an IoC container to resolve the mapping for you by registering your own controller factory that allows the container to resolve the controllers - the container will resolve the controller type and inject a concrete instance of the interface.

Example using Castle Windsor

in global.asax in your MvcApplication class:

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());
}

WindsorControllerFactory class

using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.Core.Resource;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

public class WindsorControllerFactory : DefaultControllerFactory
{
    WindsorContainer container;

    public WindsorControllerFactory()
    {
        container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));

        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        foreach (Type t in controllerTypes)
            container.AddComponentWithLifestyle(t.FullName, t, Castle.Core.LifestyleType.Transient);
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        // see http://stackoverflow.com/questions/1357485/asp-net-mvc2-preview-1-are-there-any-breaking-changes/1601706#1601706
        if (controllerType == null) { return null; }

        return (IController)container.Resolve(controllerType);
    }
}
Russ Cam
Ashamed to admit I've never heard of an IoC container. I've never touched dependency injection. Can you give me an explanation and example of how it's used?
GenericTypeTea
Using Inversion of Control (IoC) aids in building loosely coupled systems by managing dependencies between types - a lot of the time an object can have dependecies on other objects, for example, your controller has a dependency on your repository to populate the model. These dependencies can be managed using an IoC container such that when a type requires an instance of another type, it asks the container for it and the container returns an instance of the type that it is configured to return...
Russ Cam
For example, your controller wants a concrete instance of `ICustomerRepository`, so it asks the container for it. We can take this a step further though, we can have the container manage the instantiation of controllers too. The advantage we have here and one of the many reasons for using an IoC container is that in instantiating the controller, the container will realise that it has a dependency on `ICustomerRepository` and instantiate an instance of that too (referred to as dependency injection).
Russ Cam
Take a look at the Martin Fowler article on IoC and Dependency Injection - http://www.martinfowler.com/articles/injection.html. You also might be interested in looking at Microsoft Unity. There's some intro articles here - http://msdn.microsoft.com/en-us/library/ff650320.aspx and here http://msdn.microsoft.com/en-us/library/ff650806.aspx
Russ Cam
Cheers Russ. I'll have a go now.
GenericTypeTea
If you have any questions, post them as questions on StackOverflow :) Your UI project will need to reference both your model project and your DAL project (it would need to do this if you weren't using IoC). You could leave creating your DAL until later and use stub/fake repositories mapped in the container configuration to be returned when resolving types for your interfaces. Maybe put the fakes in your model project, get that all working and then worry about where the real data is coming from :)
Russ Cam
Hi Russ, I actually created a separate IoC project that will reference the Dal projects. That way I can just drop and change the IoC project and it'll change the DAL. I'm going to accept this answer as I decided Unity was the way forward. If you get chance, please could you help me on this question: http://stackoverflow.com/questions/2797047/how-do-i-correctly-use-unity-to-pass-a-connectionstring-to-my-repository-classes? Much appreciated.
GenericTypeTea