319

At the risk of stepping into holy war territory, What are the strengths and weaknesses of these popular DI/IoC frameworks, and could one easily be considered the best? ..:

  • Ninject
  • Unity
  • Castle.Windsor
  • Autofac
  • StructureMap

Are there any other DI/IoC Frameworks for C# that I haven't listed here?

In context of my use case, I'm building a client WPF app, and a WCF/SQL services infrastructure, ease of use (especially in terms of clear and concise syntax), consistent documentation, good community support and performance are all important factors in my choice.

Update:

The resources and duplicate questions cited appear to be out of date, can someone with knowledge of all these frameworks come forward and provide some real insight?

I realise that most opinion on this subject is likely to be biased, but I am hoping that someone has taken the time to study all these frameworks and have at least a generally objective comparison.

I am quite willing to make my own investigations if this hasn't been done before, but I assumed this was something at least a few people had done already.

Second Update:

If you do have experience with more than one DI/IoC container, please rank and summarise the pros and cons of those, thank you. This isn't an exercise in discovering all the obscure little containers that people have made, I'm looking for comparisons between the popular (and active) frameworks.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
ocodo
  • 29,401
  • 18
  • 105
  • 117
  • 1
    Same question as [Ninject vs Unity for DI ](http://stackoverflow.com/questions/1054801/ninject-vs-unity-for-di), but it may be time for a follow-up. – Matthew Flaschen Jan 03 '11 at 03:04
  • 2
    possible duplicate of [Comparing Castle Windsor, Unity and StructureMap ](http://stackoverflow.com/questions/2216684/comparing-castle-windsor-unity-and-structuremap) – Mauricio Scheffer Jan 03 '11 at 03:50
  • @slomojo: Possible duplicate. http://stackoverflow.com/questions/4509458/ioc-comparisions-closed. Also there is link which shows the popularity of the IoC's in the answer. Have a look at it. – dhinesh Jan 03 '11 at 03:53
  • @chibacity - I've used it on... 4 projects, the first two were really basic, no issues, the second two, Unity caused us so many problems when it came to constructor injection, maintainability, readability. We ended up ripping Unity out of both and replaced it with StructureMap, constructor injection was dead simple, configuration was clean and maintainable. In my personal time I've played with AutoFac, but i find it fiddly, neeed some documentation to understand it better. The rest I can only comment on what i've read. – Phill Jan 03 '11 at 03:53
  • One issue we had was with SSRS, it was silently failing and stepping through code we couldn't figure out why it was failing, the exception was ambiguous. We spent a week writing work-arounds to get it working. Eventually when we moved to StructureMap we had another attempt at it, and within minutes using 'ObjectFactory.WhatDoIHave()' we learned that the IoC was being constructed before the assemblies were loaded into the AppDomain, so the interfaces were never registered with the concrete types. – Phill Jan 03 '11 at 04:09
  • So that, along with 'ObjectFactory.AssertConfigurationIsValid()', makes structuremap easier to debug. StructureMap allows for multiple ways of being configured, with Unity we did it in code, and we tried XML, both ways resulted in 60+ lines of XML or code to configure. Using Registries, Attributes, and XML we reduced the configuration down to about 10 lines and haven't touched it since, it was much easier to get the other developers who had never used an IoC container before, across StructureMap. So the multiple ways of being able to configure StructureMap is handy. – Phill Jan 03 '11 at 04:13
  • Constructor Injection, I never worked this one out... for repositories we inject the NHibernate ISession, I configure this like: 'x.For().HybridHttpOrThreadLocalScoped().Use(factory => factory.GetInstance().OpenSession());' and thats it, every repository gets the same session per request. The MVP who recommended we use Unity couldn't tell us how to achieve the same thing. (I would like to know if its possible so when im forced to use Unity again I can atleast do it) – Phill Jan 03 '11 at 04:15
  • @Phill re. resolving an instance to HTTP Context or TLS, Unity does not support this out of the box (as far as I know). You would need to write your own lifetime manager. – Tim Lloyd Jan 03 '11 at 04:43
  • If you want a *very* comprehensive (100+ pages) comparative treatment of Castle Windsor, StructureMap, Spring.NET, AutoFac, Unity and MEF, you *could* buy my book: http://affiliate.manning.com/idevaffiliate.php?id=1150_236 – Mark Seemann Jan 03 '11 at 08:16
  • Does it really? DI/IoC is a pretty narrow domain, and can certainly be done badly or well. This isn't like comparing broad technologies like IDE's or Languages. Granted, while certain implementations may reach a point where superiority is difficult to distinguish, and they display a level of excellence and completeness, it is well worth knowing which these are, and if a particular facet pushes one to the fore. This is not Emacs vs Vim. – ocodo Jan 03 '11 at 09:49

7 Answers7

235

While a comprehensive answer to this question takes up hundreds of pages of my book, here's a quick comparison chart that I'm still working on:

A table explaining difference between several DICs

Yahya Hussein
  • 8,767
  • 15
  • 58
  • 114
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • AutofacContrib.DynamicProxy2 provides interception... As for the custom lifetime support- as you know my answer is a bit long for this box ;) +1 for the chart though, looking forward to the final version. – Nicholas Blumhardt Jan 03 '11 at 22:29
  • 42
    I've read the MEAP of your book and have been wondering why you've left Ninject out of it? – Martin Owen Jan 05 '11 at 10:14
  • 25
    @Mark, thanks for this, hopefully your answer could include Ninject (important, not only because of the new hype surrounding it, but also due to it's use of new language features.) – ocodo Jan 05 '11 at 23:08
  • @Slomojo: Which language features are you thinking about? I'm not aware that Ninject has any language features that Castle Windsor, StructureMap or Autofac doesn't also have... – Mark Seemann Jan 06 '11 at 04:20
  • 1
    Those also use the newer features of C# (e.g. Lambdas) I was writing in comparison to Spring.Net for example. – ocodo Jan 06 '11 at 07:57
  • 3
    Ninject while similar to AutoFac is many ways, it is used by the NUGET Team, and the most popular downloaded IOC container hands down. I was disappointed that it was not in Mark's Dependency Injection in .NET book. If there is a 2nd edition at the way the industry looks, hopefully it would make it into the book. I either run into Unity, MEF (not a real DI) , Ninject, or StructurMap , I simply have yet to land on a contract or remote gig that uses spring.net or autofac etc... – Tom Stickel Mar 05 '14 at 17:27
  • 2
    Unity 3.5 already supports convention based registration:https://www.nuget.org/packages/Unity/3.5.1404. Remove one disadvantage ;-) – Vladimir Dorokhov May 19 '14 at 12:46
  • Could you please elaborate on why you think that the life time management provided by Unity is poor? Or may be at the time of your reply, it was definitely poorer than it is today. And registration by convention was also missing. Now we have more life time managers in the ASP.NET MVC (Unity.MVC) add-on for Unity (`PerRequestLifetimeManager`) and also `Microsoft.Patterns.Unity.RegistrationByConvention`. – Water Cooler v2 Aug 04 '14 at 06:10
  • 1
    @WaterCoolerv2 My answer is, as you can tell, more than three years old, and since I haven't followed Unity since then, I don't have any opinion on the current state of affairs. If you are curious about my original reason for writing as I did, I will refer you to the Unity chapter in [my book](http://amzn.to/12p90MG), since I spend several pages walking through all the problems of Unity lifetime management. – Mark Seemann Aug 04 '14 at 06:40
  • @MarkSeemann: Thanks, Mark. I've gone through the two sample chapters of your book (chapter 1 and 4, I think that were free) and have skimmed over the TOC many times. I plan to buy it soon after my travel adventures come to and end by the end of August. I have a mind to read through the book. – Water Cooler v2 Aug 04 '14 at 07:24
  • Down vote because this answer doesn't mention Ninject which was one of contianers asked about in the question – Luke T O'Brien Dec 06 '16 at 09:20
  • SimpleInjector for the WIN – P. Roe Dec 26 '16 at 22:44
  • Structuremap now supports Interception. – Gusdor Apr 18 '17 at 13:35
  • Nice table! Do you happen to have an updated version? – Ohad Schneider May 09 '17 at 07:49
  • Also, are you still a fan of Pure DI (specifically for smaller components such as micro services)? – Ohad Schneider May 09 '17 at 13:27
  • 1
    @OhadSchneider I still recommend Pure DI, unless you have very specific requirements. – Mark Seemann May 09 '17 at 14:51
  • @MarkSeemann thank you for confirming. And I see you started working on the second edition of your DI book, great news! – Ohad Schneider May 09 '17 at 18:36
116

I came across another performance comparison(latest update 10 April 2014). It compares the following:

Here is a quick summary from the post:

Conclusion

Ninject is definitely the slowest container.

MEF, LinFu and Spring.NET are faster than Ninject, but still pretty slow. AutoFac, Catel and Windsor come next, followed by StructureMap, Unity and LightCore. A disadvantage of Spring.NET is, that can only be configured with XML.

SimpleInjector, Hiro, Funq, Munq and Dynamo offer the best performance, they are extremely fast. Give them a try!

Especially Simple Injector seems to be a good choice. It's very fast, has a good documentation and also supports advanced scenarios like interception and generic decorators.

You can also try using the Common Service Selector Library and hopefully try multiple options and see what works best for you.

Some informtion about Common Service Selector Library from the site:

The library provides an abstraction over IoC containers and service locators. Using the library allows an application to indirectly access the capabilities without relying on hard references. The hope is that using this library, third-party applications and frameworks can begin to leverage IoC/Service Location without tying themselves down to a specific implementation.

Update

13.09.2011: Funq and Munq were added to the list of contestants. The charts were also updated, and Spring.NET was removed due to it's poor performance.

04.11.2011: "added Simple Injector, the performance is the best of all contestants".

Community
  • 1
  • 1
Pranav Shah
  • 3,233
  • 3
  • 30
  • 47
  • (From following the comparison Link) Updated recently, interesting to see the speed differences (plus the basic features matrix). Thanks. – lko Apr 19 '13 at 18:27
  • That comparison is not so reliable because as far as I know Ninject has extensions for both Interception and XML configuration, whereas the comparison states it doesn't. – Daniel B Sep 01 '13 at 11:46
  • 15
    this is a very quantitative comparison. what about non-performance features like file size or number of dependencies required? Additionally, subjective measures like documentation quality or usability would be helpful. My point is that there are factors to consider other than speed. – FistOfFury Jan 02 '14 at 17:48
  • 1
    Like Jeremy Miller , the author of StructureMap has said in the past... paraphrasing -- That sure there are faster IOC containers, but they lack a full set of features. – Tom Stickel Mar 05 '14 at 19:44
  • check out this: http://www.iocservicestack.net – Rajesh Jinaga Jan 23 '17 at 05:59
49

Just read this great .Net DI container comparison blog by Philip Mat.

He does some thorough performance comparison tests on;

He recommends Autofac as it is small, fast, and easy to use ... I agree. It appears that Unity and Ninject are the slowest in his tests.

asidis
  • 1,374
  • 14
  • 24
brodie
  • 5,354
  • 4
  • 33
  • 28
  • 5
    There is an update to the post [.Net DI Container Speed Redux](http://philipm.at/2011/0819/): In the bottom line, there was a wrong approach taken for Unity in the first place. With the new measurements Unity looks much better. – Volker von Einem Mar 23 '12 at 07:08
35

Disclaimer: As of early 2015, there is a great comparison of IoC Container features from Jimmy Bogard, here is a summary:

Compared Containers:

  • Autofac
  • Ninject
  • Simple Injector
  • StructureMap
  • Unity
  • Windsor

The scenario is this: I have an interface, IMediator, in which I can send a single request/response or a notification to multiple recipients:

public interface IMediator 
{ 
    TResponse Send<TResponse>(IRequest<TResponse> request);

    Task<TResponse> SendAsync<TResponse>(IAsyncRequest<TResponse> request);

    void Publish<TNotification>(TNotification notification)
        where TNotification : INotification;

    Task PublishAsync<TNotification>(TNotification notification)
        where TNotification : IAsyncNotification; 
}

I then created a base set of requests/responses/notifications:

public class Ping : IRequest<Pong>
{
    public string Message { get; set; }
}
public class Pong
{
    public string Message { get; set; }
}
public class PingAsync : IAsyncRequest<Pong>
{
    public string Message { get; set; }
}
public class Pinged : INotification { }
public class PingedAsync : IAsyncNotification { }

I was interested in looking at a few things with regards to container support for generics:

  • Setup for open generics (registering IRequestHandler<,> easily)
  • Setup for multiple registrations of open generics (two or more INotificationHandlers)

Setup for generic variance (registering handlers for base INotification/creating request pipelines) My handlers are pretty straightforward, they just output to console:

public class PingHandler : IRequestHandler<Ping, Pong> { /* Impl */ }
public class PingAsyncHandler : IAsyncRequestHandler<PingAsync, Pong> { /* Impl */ }

public class PingedHandler : INotificationHandler<Pinged> { /* Impl */ }
public class PingedAlsoHandler : INotificationHandler<Pinged> { /* Impl */ }
public class GenericHandler : INotificationHandler<INotification> { /* Impl */ }

public class PingedAsyncHandler : IAsyncNotificationHandler<PingedAsync> { /* Impl */ }
public class PingedAlsoAsyncHandler : IAsyncNotificationHandler<PingedAsync> { /* Impl */ }

Autofac

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();
  • Open generics: yes, implicitly
  • Multiple open generics: yes, implicitly
  • Generic contravariance: yes, explicitly

Ninject

var kernel = new StandardKernel();
kernel.Components.Add<IBindingResolver, ContravariantBindingResolver>();
kernel.Bind(scan => scan.FromAssemblyContaining<IMediator>()
    .SelectAllClasses()
    .BindDefaultInterface());
kernel.Bind(scan => scan.FromAssemblyContaining<Ping>()
    .SelectAllClasses()
    .BindAllInterfaces());
kernel.Bind<TextWriter>().ToConstant(Console.Out);
  • Open generics: yes, implicitly
  • Multiple open generics: yes, implicitly
  • Generic contravariance: yes, with user-built extensions

Simple Injector

var container = new Container();
var assemblies = GetAssemblies().ToArray();
container.Register<IMediator, Mediator>();
container.Register(typeof(IRequestHandler<,>), assemblies);
container.Register(typeof(IAsyncRequestHandler<,>), assemblies);
container.RegisterCollection(typeof(INotificationHandler<>), assemblies);
container.RegisterCollection(typeof(IAsyncNotificationHandler<>), assemblies);
  • Open generics: yes, explicitly
  • Multiple open generics: yes, explicitly
  • Generic contravariance: yes, implicitly (with update 3.0)

StructureMap

var container = new Container(cfg =>
{
    cfg.Scan(scanner =>
    {
        scanner.AssemblyContainingType<Ping>();
        scanner.AssemblyContainingType<IMediator>();
        scanner.WithDefaultConventions();
        scanner.AddAllTypesOf(typeof(IRequestHandler<,>));
        scanner.AddAllTypesOf(typeof(IAsyncRequestHandler<,>));
        scanner.AddAllTypesOf(typeof(INotificationHandler<>));
        scanner.AddAllTypesOf(typeof(IAsyncNotificationHandler<>));
    });
});
  • Open generics: yes, explicitly
  • Multiple open generics: yes, explicitly
  • Generic contravariance: yes, implicitly

Unity

container.RegisterTypes(AllClasses.FromAssemblies(typeof(Ping).Assembly),
   WithMappings.FromAllInterfaces,
   GetName,
   GetLifetimeManager);

/* later down */

static bool IsNotificationHandler(Type type)
{
    return type.GetInterfaces().Any(x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof(INotificationHandler<>) || x.GetGenericTypeDefinition() == typeof(IAsyncNotificationHandler<>)));
}

static LifetimeManager GetLifetimeManager(Type type)
{
    return IsNotificationHandler(type) ? new ContainerControlledLifetimeManager() : null;
}

static string GetName(Type type)
{
    return IsNotificationHandler(type) ? string.Format("HandlerFor" + type.Name) : string.Empty;
}
  • Open generics: yes, implicitly
  • Multiple open generics: yes, with user-built extension
  • Generic contravariance: derp

Windsor

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • Open generics: yes, implicitly
  • Multiple open generics: yes, implicitly
  • Generic contravariance: yes, with user-built extension
stratovarius
  • 3,720
  • 1
  • 30
  • 26
21

Actually there are tons of IoC frameworks. It seems like every programmer tries to write one at some point of their career. Maybe not to publish it, but to learn the inner workings.

I personally prefer autofac since it's quite flexible and have syntax that suits me (although I really hate that all register methods are extension methods).

Some other frameworks:

Steven
  • 166,672
  • 24
  • 332
  • 435
jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Hi @abatishchev! :) ... the original idea was to make sure third-party and built-in methods were on the same footing; many "register" methods have to ship separately (e.g. `RegisterControllers()` for MVC) so I thought designing around that case was worthwhile. (This was designed 5+ years ago.) – Nicholas Blumhardt Aug 11 '14 at 00:19
  • 1
    @NicholasBlumhardt: Hi! :) Sorry for late response, notification got lost among the others. Actually such sake of consistency makes sense to me. How do you think now, how would you design it? – abatishchev Aug 27 '14 at 03:25
  • @abatishchev I do not agree with jgauffin. Extension methods are not closed for extension, they are extension. You write the core of your framework that can do all it should and with extension methods you provide some additional functionality, maybe some default helpers but anyone else is free to write their own extensions. I would say if your framework _accepts_ extension methods to extend it then it's a good framework. – t3chb0t Aug 07 '16 at 16:35
6

Well, after looking around the best comparison I've found so far is:

It was a poll taken in March 2010.

One point of interest to me is that people who've used a DI/IoC Framework and liked/disliked it, StructureMap appears to come out on top.

Also from the poll, it seems that Castle.Windsor and StructureMap seem to be most highly favoured.

Interestingly, Unity and Spring.Net seem to be the popular options which are most generally disliked. (I was considering Unity out of laziness (and Microsoft badge/support), but I'll be looking more closely at Castle Windsor and StructureMap now.)

Of course this probably (?) doesn't apply to Unity 2.0 which was released in May 2010.

Hopefully someone else can provide a comparison based on direct experience.

ocodo
  • 29,401
  • 18
  • 105
  • 117
  • 2
    Unity is pretty good. It covers most of what one needs, though some people complain about it not resolving circular dependencies. I love it. I does everything I need. – Dmitri Nesteruk Jan 03 '11 at 10:49
  • Many developpers are using **Castle.Windsor** without even knowing it. Its the default Ioc for **NHibernate**. (At least with the FluentNHibernate i downloded yesterday). I also saw a NHibernate implementation that uses LinFu nstead – k3b Jan 03 '11 at 17:54
5

See for a comparison of net-ioc-frameworks on google code including linfu and spring.net that are not on your list while i write this text.

I worked with spring.net: It has many features (aop, libraries , docu, ...) and there is a lot of experience with it in the dotnet and the java-world. The features are modularized so you donot have to take all features. The features are abstractions of common issues like databaseabstraction, loggingabstraction. however it is difficuilt to do and debug the IoC-configuration.

From what i have read so far: If i had to chooseh for a small or medium project i would use ninject since ioc-configuration is done and debuggable in c#. But i havent worked with it yet. for large modular system i would stay with spring.net because of abstraction-libraries.

k3b
  • 14,517
  • 7
  • 53
  • 85