主要的C#DI / IoC框架如何比较?
冒着步入圣战疆域的风险,这些stream行的DI / IoC框架的优点和缺点是什么,可以轻易认为是最好的? ..:
- Ninject
- 统一
- Castle.Windsor
- Autofac
- StructureMap
有没有其他的DI / IoC框架的C#,我没有在这里列出?
在我的用例的上下文中,我构build了一个客户端WPF应用程序和一个WCF / SQL服务基础架构,易用性(特别是语法清晰简洁),一致的文档,良好的社区支持和性能都是重要的因素在我的select。
更新:
所引用的资源和重复问题似乎已经过时,能否有一个知道所有这些框架的人出面并提供一些真正的洞察力?
我意识到这个问题上的大多数意见可能是有偏见的,但我希望有人花时间研究所有这些框架,并至less有一个客观的比较。
如果以前没有做过,我很乐意做自己的调查,但是我认为这是至less有一些人已经做了。
第二次更新:
如果您对多个DI / IoC容器有经验,请对这些容器的优缺点进行sorting和总结,谢谢。 这不是发现人们所有的模糊小容器的练习,我正在寻找stream行的(和主动的)框架之间的比较。
虽然这个问题的综合答案占了我的书的数百页,这是一个快速的比较图表,我还在努力:
我遇到了另一个性能比较 (最新更新2014年4月10日)。 它比较如下:
- AutoFac
- LightCore (网站是德语)
- 李林甫
- Ninject
- 娇小
- 简单的喷油器 (所有参赛者中最快的)
- Spring.NET
- StructureMap
- 统一
- 温莎
- 浩
以下是post的简要总结:
结论
Ninject绝对是最慢的容器。
MEF,LinFu和Spring.NET比Ninject快,但是还是很慢。 接下来是AutoFac,Catel和Windsor,其次是StructureMap,Unity和LightCore。 Spring.NET的缺点是,只能用XMLconfiguration。
SimpleInjector,Hiro,Funq,Munq和Dynamo提供了最好的性能,它们非常快。 给他们一个尝试!
尤其是简单的喷油器似乎是一个不错的select。 它非常快,有一个很好的文档,并支持先进的scheme,如拦截和通用装饰器。
您也可以尝试使用通用服务select器库,并希望尝试多个选项,并查看哪些最适合您。
关于通用服务select器库的一些通知:
该库提供了对IoC容器和服务定位器的抽象。 使用库允许应用程序间接访问function而不依赖于硬引用。 希望通过使用这个库,第三方应用程序和框架可以开始利用IoC /服务位置,而不必将自己绑定到特定的实现。
更新
2011年9月 13日 : Funq和Munq被列入参赛名单。 图表也被更新了,由于性能不佳,Spring.NET被删除了。
2011年11月4日: “添加简单的喷油器 ,performance是所有参赛者中最好的”。
只要阅读Philip Mat这个伟大的.Net DI容器比较博客 。
他做了一些彻底的性能比较testing;
- Autofac
- StructureMap
- Ninject
- 统一
- Castle.Windsor
- Spring.Net
他build议Autofac,因为它小巧,快速,易于使用…我同意。 Unity和Ninject似乎是他testing中速度最慢的。
免责声明:截至2015年初, Jimmy Bogard的IoC容器function有很大的比较,下面是一个总结:
比较容器:
- 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; }
然后我创build了一组请求/响应/通知:
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 { }
我感兴趣的是关于generics的容器支持的几件事情:
- 设置打开的generics(轻松注册IRequestHandler <,>)
- 设置多个注册的开放式generics(两个或更多的INotificationHandlers)
通用差异的设置(注册基础INotification的处理程序/创build请求pipe道)我的处理程序非常简单,只是输出到控制台:
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();
- 开放generics:是的,隐式的
- 多个开放的generics:是的,隐式的
- 一般的反变化:是的,明确的
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);
- 开放generics:是的,隐式的
- 多个开放的generics:是的,隐式的
- 通用反转:是的,用户构build的扩展
简单的喷油器
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);
- 开放generics:是的,明确的
- 多种开放的generics:是的,明确的
- 一般的反变化:是的,含蓄地(与更新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<>)); }); });
- 开放generics:是的,明确的
- 多种开放的generics:是的,明确的
- 一般的反变化:是的,含蓄地
统一
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; }
- 开放generics:是的,隐式的
- 多个开放的generics:是的,用户build立的扩展
- 通用反转:derp
温莎
var container = new WindsorContainer(); container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces()); container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces()); container.Kernel.AddHandlersFilter(new ContravariantFilter());
- 开放generics:是的,隐式的
- 多个开放的generics:是的,隐式的
- 通用反转:是的,用户build立的扩展
实际上有大量的IoC框架。 看起来每个程序员都试图在他们职业生涯的某个时候写一个。 也许不发表它,而是要学习内在的运作。
我个人更喜欢autofac,因为它非常灵活,并有适合我的语法(虽然我真的恨所有注册方法是扩展方法)。
其他一些框架:
那么,环顾目前我发现的最好的比较是:
-
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似乎排在前列。
同样从民意调查来看, Castle.Windsor和StructureMap似乎是最受青睐的。
有趣的是, Unity和Spring.Net似乎是最普遍不喜欢的stream行选项。 (我从懒惰(和微软徽章/支持)考虑Unity,但我现在将更加关注Castle Windsor和StructureMap。)
当然这可能(?)不适用于2010年5月发布的Unity 2.0。
希望别人能够根据直接经验提供一个比较。
在我写这段文字的时候,请查看一下包括linfu和spring.net在内的google代码的net-ioc-frameworks的比较。
我和spring.net一起工作过:它有许多function(aop,libraries,docu,…),在dotnet和java世界里有很多的经验。 function模块化,所以你不必采取所有function。 这些function是像数据库抽象,日志摘要这样的常见问题的抽象概念。 然而,执行和debuggingIoCconfiguration是很困难的。
从目前为止我读到的:如果我不得不select一个小型或中型项目,我会使用ninject,因为iocconfiguration完成并可以在c#中debugging。 但我还没有与它合作。 对于大的模块化系统,我会留在spring.net,因为抽象库。