How do the major C# DI/IoC frameworks compare? [closed]
Asked Answered
M

7

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.

Midcourse answered 3/1, 2011 at 2:55 Comment(10)
Same question as [Ninject vs Unity for DI ](https://mcmap.net/q/88565/-ninject-vs-unity-for-di-closed), but it may be time for a follow-up.Accentor
possible duplicate of [Comparing Castle Windsor, Unity and StructureMap ](#2217184)Ginsburg
@slomojo: Possible duplicate. https://mcmap.net/q/88567/-ioc-comparisions-closed. Also there is link which shows the popularity of the IoC's in the answer. Have a look at it.Overreach
@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.Apical
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.Apical
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.Apical
Constructor Injection, I never worked this one out... for repositories we inject the NHibernate ISession, I configure this like: 'x.For<ISession>().HybridHttpOrThreadLocalScoped().Use(factory => factory.GetInstance<ISessionFactory>().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)Apical
@Apical 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.Erinerina
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: affiliate.manning.com/idevaffiliate.php?id=1150_236Clanton
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.Midcourse
C
236

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

Clanton answered 3/1, 2011 at 10:49 Comment(17)
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.Fogbound
I've read the MEAP of your book and have been wondering why you've left Ninject out of it?Landsknecht
@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.)Midcourse
@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...Clanton
Those also use the newer features of C# (e.g. Lambdas) I was writing in comparison to Spring.Net for example.Midcourse
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...Loach
Unity 3.5 already supports convention based registration:nuget.org/packages/Unity/3.5.1404. Remove one disadvantage ;-)Phyllome
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.Rein
@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, since I spend several pages walking through all the problems of Unity lifetime management.Clanton
@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.Rein
Down vote because this answer doesn't mention Ninject which was one of contianers asked about in the questionTransitory
SimpleInjector for the WINNador
Structuremap now supports Interception.Tammy
Nice table! Do you happen to have an updated version?Turkic
Also, are you still a fan of Pure DI (specifically for smaller components such as micro services)?Turkic
@OhadSchneider I still recommend Pure DI, unless you have very specific requirements.Clanton
@MarkSeemann thank you for confirming. And I see you started working on the second edition of your DI book, great news!Turkic
L
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".

Locksmith answered 13/9, 2011 at 20:13 Comment(5)
(From following the comparison Link) Updated recently, interesting to see the speed differences (plus the basic features matrix). Thanks.Anchovy
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.Griseofulvin
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.Selena
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.Loach
check out this: iocservicestack.netPrimitive
S
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.

Strand answered 10/8, 2011 at 22:26 Comment(1)
There is an update to the post .Net DI Container Speed Redux: In the bottom line, there was a wrong approach taken for Unity in the first place. With the new measurements Unity looks much better.Luciano
S
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
Smokeproof answered 30/10, 2015 at 14:59 Comment(2)
Excellent! Btw, the above summary missed Windsor, but it's available in the Jimmy's original article.Draggletailed
Wow nobody warned about it before (: I added windsor, thanks @DraggletailedSmokeproof
P
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:

Passifloraceous answered 3/1, 2011 at 6:5 Comment(3)
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.)Fogbound
@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?Monas
@Monas 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.Edyth
M
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.

Midcourse answered 3/1, 2011 at 9:36 Comment(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.Reticular
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 nsteadJetty
J
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.

Jetty answered 3/1, 2011 at 5:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.