What is Inversion of Control and what problems does it solve
Inversion of control can be described as the reversal of control in parts of a program. Another way of looking at it is a way of removing dependencies from the code you write. A good way to see what this means and how it works is to look at how we write code. If you had two classes in which one class used the other, normally there would a reference to the code in the following way:
Class A { public B secondClass = new B(); }
This creates a dependency on B which could be bad since the two classes are now tightly coupled. Wikipedia defines it as object coupling that is bound at run time. So in the previous example the high coupling between the two classes could be lessened, ensuring that any changes in the Class B would not adversely affect A.
What IOC containers are there out there
I have used three different frame works but there are a few of them out there:
- Spring.Net
- Castle Windsor
- Autofac
Others I have not used
- Structure map
- Ninject
- Unity
Example of IOC using Castle Windsor.
The first step is to use nuget to install the packages in the solution:
From There we need to add the windsor container into global.asax in the Application_Start method:
public static IWindsorContainer Container; //This has to be static protected void Application_Start() { //Was already here AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); //Added this ConfigureIoC(); } private static void ConfigureIoC() { Container = ContainerFactory.Create(); }
I have added a factory to setup the container:
public static class ContainerFactory { private static IWindsorContainer Container { get; set; } public static IWindsorContainer Create() { Container = new WindsorContainer(); Container.Install(FromAssembly.This()); ConfigureControllers(); return Container; } private static void ConfigureControllers() { var controllerFactory = new WindsorControllerFactory(Container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); } }
Once you have configured the factory all you need to do is configure what we call the installers. You can do this in one file but we have separated them. Here is an example of some of the installers:
The first one is to configure all of our services:
public class ServiceInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( AllTypes.FromAssemblyNamed("Assembly.Project.Service") .Where(Component.IsInNamespace("Assembly.Project.Service.Services")) .WithService.DefaultInterfaces() .Configure(c => c.LifestyleTransient())); } }
The next one will configure all of our controllers:
public class ControllersInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(AllTypes.FromThisAssembly() .BasedOn<IController>() .If(t => t.Name.EndsWith("Controller")) .Configure(c => c.LifestyleTransient())); } }
The last part is to write the controller with the properties you need. I have used constructor injection in this example, so all properties that will be injected via the constructor:
namespace Namespace.Web.Controllers { public class HomeController : Controller { private IService _service; public HomeController(IService service) { _service = service; } [HttpGet] public ActionResult Index() { Model model = _service.DoSomeThing(); return View(model); } } }
This should help with configuring your solution with castle. Hope it has been helpful.