I've been researching how to design a MVC 4 web solution that follows the Dependency Inversion Principle and utilizes a Dependency Injection (DI) container that is configured fluently (i.e. with compile time type checking).
Many examples of ASP.NET MVC 4 Dependency Injection I've found focus on the specifics for implementing DI into the entry points the MVC framework provides. I find myself gravitating towards the resulting layered approach (dependencies shown with red arrows):
Which, unfortunately, repeats the conventional dependency model where high-level modules depend on low-level ones. Following the principle of Dependency Inversion the IService interface is moved into the WebProject. Unfortunately this creates a circular reference between the two projects:
To avoid the circular reference the CompositionRoot is moved into it's own Project:
Leaving me with the problem of how to bootstrap the container (now I can't directly reference it from within the WebProject)?
With a little help from the best way to get the directory from which an assembly is executing initialization can be achieved through reflection.
var assembly = System.Reflection.Assembly.LoadFile(Helper.AssemblyDirectory + "/DependencyInjectionProject.dll");
var type = assembly.GetType("DependencyInjectionProject.Bootstrapper");
IDependencyResolver resolver = (IDependencyResolver)type.GetMethod("Initialise").Invoke(null, null);
DependencyResolver.SetResolver(resolver);
To make building easy I've set the DependencyInjectionProject's build target to the WebProject bin directory. I've met my objectives; inverted dependencies and compile time checked container configuration but I'm not completely happy with this approach due to the frequent build target collisions that occur when running the WebProject in IIS Express.
I am very interested in hearing other experiences and approaches towards meeting these requirements. Should I forgo compile time configuration and adopt a text based one? Is there an obvious structuring of the layers that avoids the pitfalls of circular dependencies that I'm not seeing?