vrijdag 26 april 2013

IoC containers compared

There are quite a few different IoC containers for .Net. How does one decide which IoC container to use? There are performance comparisons made, but as even the slowest IoC container only takes 0.04 milliseconds to resolve a dependency, performance is not a good discriminator.
I've decided to do a feature comparisons of Autofac, Structuremap and Unity. The results can be read below.



Basic registration

Basic registration is easy in each of the frameworks.

Structuremap

ObjectFactory.Initialize(x =>

{
   x.For<ISomethingService>()
     .Use<SomethingService>();
}


Autofac

var builder = new ContainerBuilder();

builder.RegisterType<SomethingService>()
          .As<ISomethingService>();


Unity

IUnityContainer container = new UnityContainer();

container.RegisterType<ISomethingServiceSomethingService>();




Registration of a singleton

Setting lifetimescope options like "singleton" are easy in each of the frameworks.


Structuremap

ObjectFactory.Initialize(x =>

{
   x.For<IThatService>()
     .Singleton()
     .Use<ThatService>();

}



Autofac

var builder = new ContainerBuilder();

builder.RegisterType<ThatService>()
          .As<IThatService>()
          .SingleInstance();





Unity

IUnityContainer container = new UnityContainer();

container.RegisterType<IThatServiceThatService>(
                                                                new ContainerControlledLifetimeManager());

Personally I don't like the term ContainerControlledLifetimeManager. Structuremap and Autofac have more obvious terms (Singleton and SingleInstance).



Autoscanning assemblies

Some frameworks provide ways to automatically register all or specific classes from an assembly. This can really be helpfull if for example you want to register all repositories in your solution and you don't want to write every registration by hand.


Structuremap

ObjectFactory.Initialize(x =>

{
   x.Scan(a =>
             {
                a.Assembly("[AssemblyName]");
                a.WithDefaultConventions();
             });

}


Structuremap can autoscan assemblies, but you can't set any lifetimeoptions. If you want to do that, you have to write some custom code.


Autofac

var builder = new ContainerBuilder();


builder.RegisterAssemblyTypes(Assembly.Load("[AssemblyName]"))
                .Where(t => t.Name.EndsWith("Repository"))
                .AsImplementedInterfaces()
                .SingleInstance();


Autofac has the option to set lifetimeoptions. In the example above all repositories are registered as singletons (SingleInstance).

Unity

As far as I know, Unity doesn't provide a way to autoscan assemblies out of the box.
With Unity you can autoregister assemblies by using Unity Auto Registration. (Thanks to Björn Bailleul for letting me know).


Organizing registrations

In real-life you want to organize the registrations and not put everything in the global.asax.

Structuremap

public class UnitOfWorkRegistry : Registry
{
   public UnitOfWorkRegistry()
   {
      For<IUnitOfWork>().Singleton().Use<UnitOfWork>();
   }
}


ObjectFactory.Initialize(x =>

{
   x.AddRegistry<UnitOfWorkRegistry>();
}


Structuremap doesn't have a way to set any properties or pass constructor variables to the Registry.


Autofac

public class MyModule : Autofac.Module
{
   public bool RandomProperty { get; set; }

   protected override void Load(ContainerBuilder builder)
   {
      if (RandomProperty)
         builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().SingleInstance();
   }
}

builder.RegisterModule(new MyModule() { RandomProperty = true });


Unity

I didn't find a way to use modules or registries with Unity. If anyone knows how to do this, please let me know.


Documentation

Structuremap

The documentation of Structuremap is incomplete and outdated. For example the next text can be seen on the homepage of structuremap:

The current version 2.5.2 was released in January 2009, with a 2.6 release scheduled for no later than the end of January 2009.

At the moment of writing this blog the current version of Structuremap is 2.6.4.1 and updated on august 13, 2012. But there are more problematic errors, like the quickstart, which says you can use the next statement to register a type:

x.ForRequestedType<IValidator>()
 .TheDefaultIsConcreteType<Validator>();

And indeed you can, but the ForRequestedType and TheDefaultIsConcreteType are deprecated, so they shouldn't be on the quickstart anymore.

Another major gap in the documentation is that there's no information about ASP.Net MVC integration on the Structuremap homepage.



Autofac

I have no criticism on the Autofac documentation. It is frequently updated (last update was 59 minutes ago since writing this text), and it's extensive. The most important chapters are easy to be found on the wiki on the Autofac homepage.



Unity

I find it difficult to find the documentation on Unity. This is the path I had to follow for the online documentation:

1. Go to the Unity homepage (http://unity.codeplex.com/)
2. Click on the Documentation tab (http://unity.codeplex.com/documentation)
3. Click on the link to MSDN (http://msdn.microsoft.com/en-us/library/ff647202)
4. Click on the link to Unity 3 (http://msdn.microsoft.com/en-us/library/dn170416.aspx)
5. I've found only a link to a guide that can be downloaded, not what I was looking for.
6. Click on the link to Unity 2.0 (http://msdn.microsoft.com/en-us/library/ff663144.aspx)
7. Found the online info about configuring Unity (http://msdn.microsoft.com/en-us/library/ff660846(v=pandp.20).aspx)

The online documentation itself is extensive and tedious. I find it diffucult to navigate. For example the text about MVC integration is nowhere to be found.

The PDF that can be downloaded looks a lot more inviting than the online documentation.


Final verdict

Autofac has the most extensive featureset when it comes to registration of classes. The documentation is up to date and easy to read.

Structuremap does a pretty good job too, but lacks in autoscanning features. The documentation is outdated.

Unity doesn't provide a way to autoscan assemblies, which leads to writing a lot of code yourself if you need that. (corrected by remark of Björn Bailleul) I didn't find a way to organize the registrations like the way it can be done with Autofac or Structuremap. The documentation is hard to find and difficult to navigate.

5 opmerkingen:

  1. Edo,

    Unity allows you to use Unity.AutoRegistration to allow you to auto scan assemblies with custom in- and exclusions if needed.

    BeantwoordenVerwijderen
  2. Hi Björn, thanks for your comment. I've made the corrections in the text.

    BeantwoordenVerwijderen
  3. Great post. Poor documentation can be just as bad as lack of features.

    BeantwoordenVerwijderen
  4. Nice to see you busy with IoC, Edo.
    Thanks for the info. It's the same info I was expecting to find in the book "Dependency Injection in .NET", but I never gotten around to it.

    BeantwoordenVerwijderen
  5. That's what I wanted to hear, thank you very much, Edo :)

    BeantwoordenVerwijderen