冒着进入圣战的风险,这些流行的DI/IoC框架的优点和缺点是什么,其中一个可以轻易地被认为是最好的吗?..:

Ninject 团结 城堡。温莎 Autofac StructureMap

还有其他我没有在这里列出的c# DI/IoC框架吗?

在我的用例中,我正在构建一个WPF客户端应用程序,WCF/SQL服务基础设施,易用性(特别是在清晰简洁的语法方面),一致的文档,良好的社区支持和性能都是我选择的重要因素。

更新:

所引用的资源和重复的问题似乎已经过时了,那些了解所有这些框架的人能站出来提供一些真正的见解吗?

我知道大多数关于这个主题的观点可能是有偏见的,但我希望有人花时间研究所有这些框架,至少有一个总体上客观的比较。

如果以前没有人做过这样的调查,我很愿意自己做,但我认为至少有一些人已经做过了。

第二次更新:

如果您有使用多个DI/IoC容器的经验,请对它们的优缺点进行排序和总结,谢谢。这并不是一个发现人们所做的所有晦涩的小容器的练习,我正在寻找流行(和活跃)框架之间的比较。


当前回答

我遇到了另一个性能比较(2014年4月10日的最新更新)。它比较了以下内容:

AutoFac LightCore(网站为德语) LinFu Ninject 娇小的 简单注入器(所有参赛者中最快的) 春天。网 StructureMap 团结 温莎 宏

以下是这篇文章的简要总结:

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.

您还可以尝试使用公共服务选择器库,并希望尝试多个选项,看看哪个最适合您。

关于公共服务选择器库的一些信息:

这个库提供了IoC容器和服务的抽象 定位器。使用库允许应用程序间接访问 不依赖于硬引用的功能。希望是 使用这个库,第三方应用程序和框架可以启动 来利用IoC/服务位置,而不将自己束缚在 具体的实现。

更新

13.09.2011: Funq和Munq加入参赛名单。图表也更新了,Spring。NET由于性能不佳而被删除。

04.11.2011:“Simple Injector的表现是所有选手中最好的”。

其他回答

免责声明:截至2015年初,Jimmy Bogard对IoC容器特性进行了大量的比较,以下是摘要:

容器相比:

Autofac Ninject 简单的注射器 StructureMap 团结 温莎

这个场景是这样的:我有一个接口IMediator,在这个接口中我可以向多个接收者发送单个请求/响应或通知:

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; 
}

然后我创建了一个请求/响应/通知的基本集:

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 { }

我对一些关于泛型容器支持的事情很感兴趣:

开放泛型的设置(很容易注册IRequestHandler<,>) 设置开放泛型的多个注册(两个或多个) INotificationHandlers)

通用变体的设置(为基本INotification注册处理程序/创建请求管道) 我的处理程序非常简单,它们只是输出到控制台:

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 */ }

自发法克

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();

开放泛型:是的,隐式地 多重开放泛型:是的,隐式地 泛型逆变:是的,显式的

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);

开放泛型:是的,隐式地 多重开放泛型:是的,隐式地 一般的矛盾性:是的,使用用户构建的扩展

简单的注射器

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);

开放泛型:是的,显式地 多重开放泛型:是的,显式地 泛型逆变:是,隐式的(更新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<>));
    });
});

开放泛型:是的,显式地 多重开放泛型:是的,显式地 泛型逆变:是的,隐式的

团结

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;
}

开放泛型:是的,隐式地 多个开放泛型:是的,带有用户构建的扩展 泛型逆变:derp

温莎

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());

开放泛型:是的,隐式地 多重开放泛型:是的,隐式地 一般的矛盾性:是的,使用用户构建的扩展

我遇到了另一个性能比较(2014年4月10日的最新更新)。它比较了以下内容:

AutoFac LightCore(网站为德语) LinFu Ninject 娇小的 简单注入器(所有参赛者中最快的) 春天。网 StructureMap 团结 温莎 宏

以下是这篇文章的简要总结:

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.

您还可以尝试使用公共服务选择器库,并希望尝试多个选项,看看哪个最适合您。

关于公共服务选择器库的一些信息:

这个库提供了IoC容器和服务的抽象 定位器。使用库允许应用程序间接访问 不依赖于硬引用的功能。希望是 使用这个库,第三方应用程序和框架可以启动 来利用IoC/服务位置,而不将自己束缚在 具体的实现。

更新

13.09.2011: Funq和Munq加入参赛名单。图表也更新了,Spring。NET由于性能不佳而被删除。

04.11.2011:“Simple Injector的表现是所有选手中最好的”。

请阅读Philip Mat撰写的。net DI容器比较博客。

他做了一些彻底的性能比较测试;

Autofac StructureMap Ninject 团结 城堡。温莎 春天。网

他推荐Autofac,因为它体积小,速度快,而且容易使用。我同意。在他的测试中,Unity和Ninject似乎是最慢的。

虽然对这个问题的全面回答占据了我书中数百页的篇幅,但这里有一个我仍在制作的快速比较图表:

好吧,环顾四周之后,我发现目前为止最好的比较是:

http://www.sturmnet.org/blog/2010/03/04/poll-ioc-containers-for-net http://www.sturmnet.org/blog/2010/03/04/poll-results-ioc-containers-for-net

这是2010年3月进行的一项民意调查。

我感兴趣的一点是,那些使用过DI/IoC框架并喜欢或不喜欢它的人,StructureMap似乎名列前茅。

从民调来看,卡塞尔。Windsor和StructureMap似乎是最受欢迎的。

有趣的是,Unity和Spring。Net似乎是最普遍不受欢迎的选择。(我考虑Unity是出于懒惰(以及微软的徽章/支持),但我现在会更仔细地研究温莎城堡和StructureMap。)

当然,这可能不适用于2010年5月发布的Unity 2.0。

希望其他人可以根据直接经验进行比较。