How Autofac’s Dynamic instantiation solves the service locator problem for ViewModels

Yesterday ive blogged about why I moved to Autofac. Now I want to show a really nice feature of Autofac which solves the service locator problem when you work with child ViewModels.

Let me give this example:

public class OrderViewModel
{
    public ObservableCollection<OrderLineViewModel> OrderLines { get; set; }

    public OrderViewModel(OrderDao orderDao)
    {
        OrderLines = new ObservableCollection<OrderLineViewModel>();

        foreach(var orderLine in orderDao.GetOrderLines())
        {
            var viewModel = IoC.Resolve<OrderLineViewModel>(orderLine);
            OrderLines.Add(viewModel);
        }
    }
}

What is the problem here? We need to create an OrderLineViewModel for each OrderLine we get from the database. We can not know how much OrderLines we need at build time of the OrderViewModel so we can not use constructor inject for that.

We have to use IoC.Resolve which is commonly known as service locator pattern. The real problem with that is that such a call only fails (because of missing dependencies) when it happens not on that point where the constructor of the root is resolved. In this example weights not much, but if this happens to code which is only used once in a month you have a problem.

So how Autofac can solve that:

public class OrderViewModel
{
    public ObservableCollection<OrderLineViewModel> OrderLines { get; set; }

    public OrderViewModel(OrderDao orderDao, Func<OrderLineViewModel,OrderLine> orderLineViewModelFactory)
    {
        OrderLines = new ObservableCollection<OrderLineViewModel>();

        foreach(var orderLine in orderDao.GetOrderLines())
        {
            var viewModel = orderLineViewModelFactory(orderLine);
            OrderLines.Add(viewModel);
        }
    }
}

What is the difference? The func is a dynamic service locator provided by Autofac, but instead at call time, Autofac has now the chance to know what types you need at runtime and now it can satisfy all dependencies at resolve time of the root objects constructor.

So what happens is that it fails now at the root of you application. Not one month later when your client calls this one view with the missing dependencies.

The same way Autofac supports Lazy<T> which is new in .Net 4.0 and resolves once on the first call. You can read more about that in this blog post from Nicholas Blumhardt which is the author of Autofac.

Why I moved from Windsor to Autofac

A long while ago as I started with dependency injection and inversion of control, I started with the container the most people use at this time. Since a read a lot of Ayende I naturally started with Castle Windsor.

Now after a long time of using it, it dose not feel very well anymore. The registration interface is fluent, but looks ugly and it is not very clear what a lot of methods on the configuration interface do. At the end Windsor feels old and ugly (like it is with Monorail compared to MVC).

So to look at the other containers I have to define my requirements:

  • It should be simple
  • It should be extendable
  • It should have a documentation

Now what containers are existing today. Here is a list of the most known ones with some initial thoughts on it.

  • Spring.Net
    • Large and cumbersome port from Java.
    • Looks like a lot of things a never need
  • StructureMap
    • Modern but I don’t like its over fluent interface (I don’t consider fluent interface which trying to build sentences very helpful)
  • Ninjet
    • Small but it saw a lot of attributes on the sample code (don’t like to do all with attributes since CAB)
    • The same about the fluent interfaces like StructureMap
  • Autofac
    • Small and very extendable codebase
    • Interface looks simple and clean

So it seems Autofac is the right to try. And after using it now for some time, I really really like it.

Autofac has a clean and simple core which can be easily extended. And itself makes a lot of use of that. It have nearly all the functions that Windsor and the other containers have, but as extension to the core. Examples are XML configuration, ASP MVC, Proxy and a lot more. Autofac can create components with parameters from its type or position not only from its name like Windsor dose.

So how dose a simple registration looks like in Autofac?

var builder = new ContainerBuilder();

builder.RegisterType<MyComponent>()
    .As<IMyComponent>()
    .SingleInstance();

var container = builder.Build();

container.Resolve<IMyComponent>();

I also like the way you resolve multiple instances:

var assembly = Assembly.GetExecutingAssembly();

builder.RegisterAssemblyTypes(assembly)
    .Where(t => t.Name.EndsWith("Rule"))
    .As<IOrderRule>();

var container = builder.Build();

var rules = container.Resolve<IEnumerable<IOrderRule>>();

Conclusion

At the most it’s a matter of taste yes, but I can only suggest that you try it out yourself.