Thursday, July 18, 2013

Nested Dependencies in MVC4

Given how complex the average MVC4 application can become, it is likely that you are going to come across the situation where you build up a dependency chain. It may look like this: Controller -> Provider/Manager -> Dependency

 A common scenario may be that your controller needs a Lookup Manager, and that manager needs a cached query passed in. In this scenario, the Unity.Mvc4 nuGet package comes into play. Here is our home controller:

// Home controller
public class HomeController : AsyncController
{
	private ILookupManager<StatusLookup> statusLookup; 

	// constructor with lookup dependency
	public HomeController(ILookupManager<StatusLookup> statusLookup)
	{
		this.statusLookup = statusLookup;
	}
}
Notice that the constructor requires the StatusLookup. Here is the Status Manager implementation. Observe that it is a generic class, expecting a StatusLookup object. The constructor requires a query passed in (of type IQuery).

//LookupManager.cs
public class LookupManager<T> : ILookupManager<T> where T : ILookupField
{
	private IQuery<T> _query;

	// lookup manager has a Query dependency
	public LookupManager(IQuery<T> query)
	{
		_query = query;
	}

	public List<T> Lookup()
	{
		// return lookup query result
		return _query.Get();
	}
}

This is where life gets easy. After installing the Unity.Mvc4 nuGet package, our MVC project gains a "boostrapper" class. This provides us with a simple mechanism to get any dependency into any class in our MVC app. It works by utilising the Unity Dependency Injection container.

// Boostrapper.cs
// Added by the Unity.Mvc4 NuGet package
private static IUnityContainer BuildUnityContainer()
{
	var container = new UnityContainer();

	// initialise Status lookup
	container.RegisterType<IQuery<StatusLookup>, QueryStatusLookup>();
	
	// make Status lookup available to mvc4 controllers
	container.RegisterType<ILookupManager<StatusLookup>, LookupManager<StatusLookup>>();
	
	RegisterTypes(container);
	return container;
}

If we have a look at the BuildUnityContainer() method, there are two calls to container.RegisterType(). The first is to provide the IQuery dependency to StatusLookup. The second is to provide the StatusLookup dependency to our HomeController.

To keep it all manageable, make sure your dependencies are passed using an interface (ILookupManager, and IQuery in my case).

No comments:

Post a Comment