Note to RSS users: There are embedded spreadsheets in this posts that Google Reader silently hides. I prefer RSS myself, but for this post Zoho features are very useful and, unfortunately, I see no way to make it usable in Google Reader. Sorry about that.

See also: .NET DI (IoC) Frameworks, Revisited.

Update: Several people have pointed to the fact that some issues mentioned in my post are no longer relevant. I will try to mention it, but in general this post reflects only the versions I have listed in the previous one.

However, Jeremy Miller (author of StructureMap) has pointed to a significant oversight in my review: StructureMap is not limited to static APIs. Since this error is so large and relevant to the reviewed version, I am completely rewriting this part now.

I have finished the previous post with a summary of basic injection/autowiring features. It would be great to say that I will cover all remaining features in this part.

However, it is not possible to review and compare every single feature of all IoC frameworks, and some things (like AOP) I felt to be outside of the scope of IoC functionality. So this review will be somewhat limited, but, I hope, still useful.

4. Lifestyles

As you can see, all frameworks support two basic lifestyles, transient and singletons. In addition to this, all of them have an ability to define custom lifestyles (the specific APIs are named quite differently between frameworks).

I have also added support for custom instance registration to the same table (custom instances are instances built outside of the container and then provided as an implementation of some service interface). This support is also strong in all reviewed frameworks.

The interesting thing that can be learned here is that extensible lifestyles system is a baseline feature for any IoC framework, something that must be supported. This is quite understandable for singletons and transients, but it is nice to see that extensibility is also very popular.

5. Advanced resolution

While the previous section deals with the baseline features, this section contains advanced features that I feel should be a new baseline.

So, what is it all about?

Open generics injection is an ability to register open generic types and receive specific generic types on demand. Basically, it is about registering Component<> as IService<> (not giving any generic arguments), and on request of IService<X> getting Component<X>.

It seems most framework authors tend to agree that is an useful feature, so all frameworks except Spring.Net support open generics injection. I think it is already very near to a new baseline. Thanks to Castle guys for introducing it.

List injection is something I already discussed in a previous post. It is an ability to register several IService implementations, and then get them all through IService[] (IList/IEnumerable/…) dependency. I have found it very useful, and I hoping it would become a new baseline some day.

I was very surprised by StructureMap actually supporting this functionality (I haven’t found it documented anywhere, but tests clearly show it does at least for arrays). Spring.NET, in exactly reversed fashion, has it documented, but broken in the release I have tested (see link in the table, howevers, seems to be fixed in the 1.2.0).

All other frameworks do not support list injection out of the box. It is probably implementable in most of them, so it is not such a big deal. However, I have tried to build an ArraySubDependencyResolver for Castle, and while trivial implementation works, correctly supporting circular references is a major pain I haven’t solved yet.

Unregistered resolution is also something I have talked about, as a solution to container pollution (nice rhyme!). It was a nice surprise to see that most of the frameworks except Castle and, it seems, Spring.Net have this feature. In Autofac you have to allow specific types to be resolvable, however it seems to work pretty well.

6. Final overview

The last section of this comparison will be the most subjective. The first thing I want to include is auto-mocking. Auto-mocking as a problem is well described in this post. In a nutshell, it is an ability to leverage IoC framework to automatically mock dependencies of the tested component.

IoC frameworks often position themselves as tools to simplify mocking, so I think it is important to have this simplification not only on the architectural level, but on the tool level as well. Of course, different people like different mock frameworks, however having an example integration with any mock framework really helps to implement your own.

In addition to auto-mocking, I added to the final overview some interesting features that are present in a single framework, and issues I encountered while working with specific frameworks.

As we can see, Autofac and StructureMap have an official (semi-official, for Autofac) mock framework integration example. Castle and Unity do not, however I was able to easily find appropriate samples. For Ninject and Spring.Net the containers are probably implementable, but I had no time to research it in detail.

Special features are very subjective, but two interesting things I noticed are contextual bindings in Ninject and container hierarchies in Autofac. Container hierarchies, in particular, seem to provide a solution for argument coupling. I will not describe these features in detail, however you may find it interesting to read about them.

Now special problems and pain points. In my opinion, Castle relies too much on “this is in trunk”. For example, Ayende has suggested me to use ResolveAll method to solve the generics problem I had with ResolveServices. However, there is no ResolveAll in RC3, as there is no fluent interfaces and other things. The problem with that is that I can not rely on specific version when discussing Castle with anybody, and I can not rely on having a tested and finalized version if I want to have new features.

I have not used Unity and Autofac in real work, but in tests I haven’t encountered any significant problems aside from unsupported features I already discussed.

In Ninject, there is a build problem under .Net 3.5 — sometimes I had to remove Ninject library from references and then re-add it, otherwise there was a build error about ExtensionAttribute defined twice. It was really annoying so I hope it will be fixed asap (or may be it already is).

With StructureMap, the most interesting discovery was that it is not limited to static classes. Until I was pointed to this fact, testing was quite painful, but now I can say I do not see any issues. Even better, it seems the this framework also provides an easy way to pass additional arguments by type, which is an easiest solution for argument-uncoupled factories.

Most problems with Spring.Net are based on the configuration complexity. The framework itself is powerful, but it would be nice to have autowiring and fluent configuration interface more visible in the documentation.

7. Conclusion

Judging from the comparison, I think my preferences for a new project lie between Autofac and Castle. Both frameworks understand the importance of good circular dependency resolution, and have a nice set of features. Right now I am considering Autofac, since I had a bad experience with Castle internals and hierarchical containers seem very promising. However Castle is much more mature framework, and Autofac probably has its downsides I just do not yet know about.

Ninject is probably also a good idea, I like its explicit modular system. However not being able to reliable build referencing projects on .Net 3.5 and no recursion handling are critical issues for me.

Unity is always a solid choice, it is well documented and well supported by Microsoft team. I disagree with its constructor choices and mandatory properties, but this may be less important for other people. No recursion handling here as well.

StructureMap is very interesting, since it has several surprising features that I was not expecting from any framework. For example, support for array resolution is a really neat step forward. The only important downsides of StructureMap I see now are recursion handling and constructor selection.

Spring.NET is probably the hardest choice with the most complex learning curve. It is powerful and extensible, but following the documentation it is very easy to end up with a large pile of hard-coded XML.

8. Tests and spreadsheets

To fill the gaps in the tables, I had to write some feature tests for the discussed frameworks.
MbUnit’s TypeFixture was invaluable for this purpose, since it allowed me to write each test exactly once.

You can get the test project and the complete spreadsheet here:

Code: Google Code
Spreadsheet: Zoho

The test project may also be useful to learn APIs of the reviewed frameworks.

kick it on DotNetKicks.com

  • http://ubik.com.au Nicholas Blumhardt

    Hi Andrey,

    Wow! It is very interesting to see a methodical approach to this comparison.

    Autofac does also support list registrations – but like 'resolve anything' you have to opt-in. See: http://code.google.com/p/autofac/wiki/Collections.

    As you've hinted at – like most containers you can change this behaviour by writing custom extensions. In general, you'll find Autofac is very conservative about working absolutely predictably by default.

    Cheers,

    Nick

  • http://ubik.com.au Nicholas Blumhardt

    Hi Andrey,

    Wow! It is very interesting to see a methodical approach to this comparison.

    Autofac does also support list registrations – but like 'resolve anything' you have to opt-in. See: http://code.google.com/p/autofac/wiki/Collections.

    As you've hinted at – like most containers you can change this behaviour by writing custom extensions. In general, you'll find Autofac is very conservative about working absolutely predictably by default.

    Cheers,

    Nick

  • http://ubik.com.au Nicholas Blumhardt

    Aaah – and regarding automatic registration – you can always do:

    builder.RegisterTypesAssignableTo<object>();

    :) Not really recommendable though.

    I recently ported some Prism code from Unity to Autofac, and used something similar to:

    builder.RegisterTypesMatching(t => t.Name.EndsWith(“View”));

    — just to illustrate that there is no need to use tagging interfaces or inheritance in order to work with this feature.

  • http://ubik.com.au Nicholas Blumhardt

    Aaah – and regarding automatic registration – you can always do:

    builder.RegisterTypesAssignableTo<object>();

    :) Not really recommendable though.

    I recently ported some Prism code from Unity to Autofac, and used something similar to:

    builder.RegisterTypesMatching(t => t.Name.EndsWith(“View”));

    — just to illustrate that there is no need to use tagging interfaces or inheritance in order to work with this feature.

  • http://blog.ashmind.com Andrey Shchekin

    Cool, great work!

    I think I can't update in-post chart, since it'll require me to update post text as well, and that would mean I have to consider and mention all other framework updates.
    I am looking for a way to keep an up-to-date version of charts at the net-ioc-frameworks page of Google Code, I hope to do it soon enough.

  • http://blog.ashmind.com Andrey Shchekin

    Cool, great work!

    I think I can't update in-post chart, since it'll require me to update post text as well, and that would mean I have to consider and mention all other framework updates.
    I am looking for a way to keep an up-to-date version of charts at the net-ioc-frameworks page of Google Code, I hope to do it soon enough.

  • http://blog.ashmind.com Andrey Shchekin

    Thanks!

    You have a very interesting implementation.
    I would prefer to have an automatic registration by default, since if I get into situation where I would need more than one ILogger collection, I would probably use some kind of contextual override for a requiring component anyway. But it is a question of preference.

    There are only two things that I feel are missing in your implementation — support for IService[] (since it is simplest way to define collection dependency) and and ability to register collections using non-generic API.

    Due to the first one, I can not update tests to pass right now, however, I had fixed the chart and will fix the post text as well.

  • http://blog.ashmind.com Andrey Shchekin

    Thanks!

    You have a very interesting implementation.
    I would prefer to have an automatic registration by default, since if I get into situation where I would need more than one ILogger collection, I would probably use some kind of contextual override for a requiring component anyway. But it is a question of preference.

    There are only two things that I feel are missing in your implementation — support for IService[] (since it is simplest way to define collection dependency) and and ability to register collections using non-generic API.

    Due to the first one, I can not update tests to pass right now, however, I had fixed the chart and will fix the post text as well.

  • http://blog.ashmind.com Andrey Shchekin

    Sure, I like the second approach much more.

    By the way, is it possible to resolve unregistered types in Autofac?
    I do not feel that is very important, given hierarchical containers, but I am still interested.

  • http://blog.ashmind.com Andrey Shchekin

    Sure, I like the second approach much more.

    By the way, is it possible to resolve unregistered types in Autofac?
    I do not feel that is very important, given hierarchical containers, but I am still interested.

  • alwin

    Nice comparison! I didn't know that there where so many IoC frameworks :)

    Do you know if all containers support registering services/components at any given time?
    I know Castle can do that, i'm abusing it a bit in my current project.

  • alwin

    Nice comparison! I didn't know that there where so many IoC frameworks :)

    Do you know if all containers support registering services/components at any given time?
    I know Castle can do that, i'm abusing it a bit in my current project.

  • http://blog.ashmind.com Andrey Shchekin

    Definitely not all, I think I'll add a test for that at some point.

  • http://blog.ashmind.com Andrey Shchekin

    Definitely not all, I think I'll add a test for that at some point.

  • http://ubik.com.au Nicholas Blumhardt

    The net effect is almost the same. RegisterTypesMatching() and RegisterTypesAssignableTo() are lazy – there is no scan of loaded assemblies, for instance.

    You could always create an extension method ResolveUnregistered() which could check/register first, too.

    Not sure what you mean about hierarchical containers relating to this use case – can you clarify a little?

  • http://ubik.com.au Nicholas Blumhardt

    The net effect is almost the same. RegisterTypesMatching() and RegisterTypesAssignableTo() are lazy – there is no scan of loaded assemblies, for instance.

    You could always create an extension method ResolveUnregistered() which could check/register first, too.

    Not sure what you mean about hierarchical containers relating to this use case – can you clarify a little?

  • http://ubik.com.au Nicholas Blumhardt

    On IService[] – point taken, issue raised. In the meantime you can do:

    builder.Register(c => c.Resolve<IEnumerable<X>>().ToArray());

    ..in order to adapt the default collection type onto an array type.

    I'll look into the non-generic collection registrations – may look into that in the future if there is demand.

    Thanks for the feedback!

  • http://ubik.com.au Nicholas Blumhardt

    On IService[] – point taken, issue raised. In the meantime you can do:

    builder.Register(c => c.Resolve<IEnumerable<X>>().ToArray());

    ..in order to adapt the default collection type onto an array type.

    I'll look into the non-generic collection registrations – may look into that in the future if there is demand.

    Thanks for the feedback!

  • http://blog.ashmind.com Andrey Shchekin

    The use case is to create a factory which registers several factory-specific components without polluting the original container with these components and their local scope dependencies (such as connection data). I describe the problem in detail at http://blog.ashmind.com/index.php/2008/06/23/di… .

    So, if I can create a container in place and then throw it away, it also solves the pollution problem.

  • http://blog.ashmind.com Andrey Shchekin

    The use case is to create a factory which registers several factory-specific components without polluting the original container with these components and their local scope dependencies (such as connection data). I describe the problem in detail at http://blog.ashmind.com/index.php/2008/06/23/di… .

    So, if I can create a container in place and then throw it away, it also solves the pollution problem.

  • http://colinjack.blogspot.com Colin Jack

    Good review, thanks for taking the time to do it.

  • http://colinjack.blogspot.com Colin Jack

    Good review, thanks for taking the time to do it.

  • Pingback: Putting Web snapshots to practical use » Blog Archive » I Think It’s Interesting

  • http://www.codesmithtools.com Eric J. Smith

    Great review! This is exactly what I was looking for to help clear things up for me.

  • http://www.codesmithtools.com Eric J. Smith

    Great review! This is exactly what I was looking for to help clear things up for me.

  • http://www.dstudiobali.com/webdesign/busby-seo-test-page/ Busby SEO Test

    Really like the overview and nice comparison too!

  • http://pavkul.blogspot.com Pavan Kulkarni

    Fantastic comparison. Thanks for sharing

  • http://pavkul.blogspot.com Pavan Kulkarni

    Fantastic comparison. Thanks for sharing

  • http://pavkul.blogspot.com Pavan Kulkarni

    Fantastic comparison. Thanks for sharing

  • Pingback: Weekly Web Nuggets #29 : Code Monkey Labs

  • http://www.it-sells.de/ Veyton

    awesome articel, thanks for sharing but sometimes frameworks are a bit difficult.

  • hack2root

    Please, cay you see my framework http://plugins.codeplex.com. I'm luck of time so it hadn't been documented yet, but i'm very interested in comparison to other frameworks.

  • http://blog.ashmind.com Andrey Shchekin

    I see what you are trying to achieve more as MEF/System.AddIn functionality than as basic IoC.

    I will look at it when time allows, in the meanwhile you can use test suite at
    http://code.google.com/p/net-ioc-frameworks/
    to see how it corresponds to common IoC features.

  • Pingback: .NET DI (IoC) Frameworks, Revisited » Blog Archive » I Think It’s Interesting

  • Pingback: Selecting IoC framework - Vagif Abilov's blog on .NET

  • http://www.alleinunterhalter-toni.de/ Alleinunterhalter Köln

    I think frameworks a little bit complicated, but it does an awesome job for sure.
    Thanks for sharing.

  • http://www.welscamp.de/ Angelreisen

    Awesome, thank you for sharing.

  • http://www.welscamp.de/ Angelreisen

    Awesome, thank you for sharing.

  • http://www.gutes-tagesgeld.de/ Tagesgeldvergleich

    I never liked these methods..

  • Pingback: IOC Starter « Sachin Chavan

  • welsangeln

    Thats very interesting. thanks for sharing.

  • rechnungschreiben

    Great article, very interesting. Thanks for sharing

  • Jos Krause

    Now would be a good time :-) Most frameworks are much more matured now and are sporting nice new version numbers, thanks a lot for all the investigation and time you spent on writing all of this, it was a very helpful read! :_)

  • http://www.haarpunkt.com Haarentfernung

    Thanks for sharing this interesting article.

  • http://iocbattle.com Martin

    If curious about the performance of some of the most popular IOC containers take a look http://www.iocbattle.com.
    Dynamo included is my own project to test how fast it is possible to go.

  • Naser

    Great article. But a bit dated. A update will do a lot of good.

  • Pingback: The business case for a DI framework | Semantic Architecture

  • Pingback: Vergleich von IoC-Containern - Just about .Net