How do the major C# DI/IoC frameworks compare?

112,058

Solution 1

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

Solution 2

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".

Solution 3

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.

Solution 4

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

Solution 5

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:

Share:
112,058
ocodo
Author by

ocodo

↘↓ ↘ ↘ ← ↙ ⤢↘ ↘← ↑ ↘← ↑⤡↙ → ↙ ↓↙↙ ↙ → ↗ ↙ ↘ ← ↙↙↘ ↙↘ ↙ ↑ ↘← ↘ ↑↕ ← ↓↓↑ ↙ ← ↘ ← ↙ ↕← ↗ ↔↙ ↗↓ ↑↑ →↖ ↙← ↓ ↘ → ↘ ↘ ↓↘← ↗ ↙↙ ↙ ↖ ↘ ←↓↙← ↑ ↑↑ ↑ → ↘ → ↙ ↘ ↙ ←↙ ↘ ↕ ↔ ↙↙ ← ↙ ⤡ ↑ ↘ ←↓↓↓ ↓↓↓ ↙↘ ↘→ ↘ ↙ ← ↑ ↓ ↘ → ↘ ↙ ← →↘ ↓ ↓ ↙← ↕← ↗ →↘ ↙← →↗ ↓ ↖← ↖ ↕ ↔ ↙ ↗↔ ↖ ↑↓ ↙↑ ↖← ↑↘ ↙ ↓ →↗→↖↑ ↑ ↑ ↗↖ ↑→ ↙↓ ↙ ↑ ↗ ↔ ↖↙←↙↓↖ ↗↔ ↕ ↑ → ↙ ↘ ←↗ →↖ ↘ ↕ ← ↖ ⤡ ↗ ← ↙ ↑ ↙ ↖ ↓↖← ↖ ↑ ↓ ↓↑↙ → ↘↑↓↖ ↗ ↙← ↑ ↙→ ↕ → ↖ ⤡ ↖ →↗ ↓ ↖ ↑ ↑ ↗↖

Updated on July 08, 2022

Comments

  • ocodo
    ocodo almost 2 years

    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.