主要的C#DI / IoC框架如何比较?

时间:2011-01-03 02:55:51

标签: c# dependency-injection unity-container ioc-container ninject

冒着进入神圣战争领域的风险,这些流行的DI / IoC框架有哪些优点和缺点,可以轻松地被认为是最好的? ..:

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

C#还有其他我没有在此列出的DI / IoC框架吗?

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

更新

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

我意识到关于这个主题的大多数意见可能都有偏见,但我希望有人花时间研究所有这些框架,并且至少进行了一般性的客观比较。

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

第二次更新:

如果您有多个DI / IoC容器的使用经验,请对这些容器的优缺点进行排序和总结,谢谢。这不是发现人们制作的所有模糊小容器的练习,我正在寻找流行(和主动)框架之间的比较。

7 个答案:

答案 0 :(得分:220)

虽然这个问题的综合答案占用了数百页的my book,但这是一个我仍在努力的快速比较图表:

A table explaining difference between several DICs

答案 1 :(得分:110)

我遇到了另一场演出comparison(2014年4月10日最新更新)。它比较了以下内容:

以下是帖子的简短摘要:

  

结论

     

Ninject绝对是最慢的容器。

     

MEF,LinFu和Spring.NET比Ninject更快,但仍然很漂亮   慢。接下来是AutoFac,Catel和Windsor,然后是StructureMap,   Unity和LightCore。 Spring.NET的一个缺点是,这只能是   用XML配置。

     

SimpleInjector,Hiro,Funq,Munq和Dynamo提供最好的   性能,它们非常快。试一试!

     

特别简单的注射器似乎是一个不错的选择。它非常快,有一个很好的   文档,还支持拦截等高级场景   和通用装饰。

您也可以尝试使用Common Service Selector Library,并希望尝试多种选项,看看什么最适合您。

网站上有关公共服务选择器库的一些信息:

  

该库提供了对IoC容器和服务的抽象   定位器。使用该库允许应用程序间接访问   功能而不依赖于硬引用。希望是这样的   使用此库,可以开始第三方应用程序和框架   利用IoC /服务位置而不将自己束缚到a   具体实施。

更新

13.09.2011: FunqMunq已添加到参赛者名单中。图表也进行了更新,由于性能不佳,Spring.NET被删除了。

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

答案 2 :(得分:48)

请阅读Philip Mat的这篇伟大的.Net DI container comparison blog

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

他建议Autofac因为它小巧,快速且易于使用......我同意。 UnityNinject似乎是他测试中最慢的。

答案 3 :(得分:29)

免责声明:截至2015年初,Jimmy Bogard对IoC Container 功能进行了大量比较,以下是摘要:

比较容器:

  • 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&lt;,&gt;)
  • 设置多个开放式仿制药注册(两个或更多 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 */ }

<强> Autofac

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());
  • 打开泛型:是,隐式
  • 多个开放式泛型:是,隐式
  • 通用逆转:是的,使用用户构建的扩展

答案 4 :(得分:20)

实际上有大量的IoC框架。似乎每个程序员都试图在他们职业生涯的某个阶段写一个。也许不发表它,但要学习内部运作。

我个人更喜欢autofac,因为它非常灵活,并且具有适合我的语法(尽管我真的很讨厌所有寄存器方法都是扩展方法)。

其他一些框架:

答案 5 :(得分:6)

好吧,看看目前为止我发现的最佳比较是:

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

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

同样从民意调查来看,似乎Castle.WindsorStructureMap似乎最受青睐。

有趣的是,UnitySpring.Net似乎是最受欢迎的热门选项。 (我正在考虑Unity的懒惰(以及微软徽章/支持),但我现在将更密切地关注Castle Windsor和StructureMap。)

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

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

答案 6 :(得分:5)

在我撰写此文时,请参阅列表中不包含linfu和spring.net的net-ioc-frameworks on google code的比较。

我在spring.net工作:它有很多功能(aop,库,文档......),并且在dotnet和java-world中有很多经验。功能模块化,所以你不必采取所有功能。这些功能是数据库抽象,loggingabstraction等常见问题的抽象。但是,进行和调试IoC配置是很困难的。

从我到目前为止所读到的内容:如果我必须选择一个小型或中型项目,我将使用ninject,因为ioc-configuration已完成并可在c#中调试。但我还没有使用它。对于大型模块化系统,由于抽象库,我将继续使用spring.net。

相关问题