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

发布于 2024-12-28 03:39:29 字数 1435 浏览 3 评论 0 原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

小兔几 2025-01-04 03:39:29

虽然这个问题的全面答案占据了我的书的数百页,但这里有一个快速比较图表,我仍在研究中:

解释几种 DIC 之间差异的表格

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

倾城°AllureLove 2025-01-04 03:39:29

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

以下是该帖子的快速摘要:

结论

Ninject 绝对是最慢的容器。

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

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

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

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

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

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

更新

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

04.11.2011: "添加了Simple Injector,表现是所有参赛者中最好的”。

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

穿越时光隧道 2025-01-04 03:39:29

只需阅读 Philip Mat 撰写的这篇精彩的.Net DI 容器比较博客即可。

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

他推荐Autofac 因为它体积小、速度快且易于使用......我同意。看来 UnityNinject 是他的测试中最慢的。

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.

心病无药医 2025-01-04 03:39:29

免责声明:截至 2015 年初,功能进行了很好的比较13/generic-variance-in-di-containers/" rel="noreferrer">Jimmy Bogard,这里是一个总结:

比较容器:

  • Autofac
  • Ninject
  • Simple Injector
  • StructureMap
  • Unity
  • Windsor

场景是这样的:我有一个接口 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 */ }

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<>));
    });
});
  • 开放泛型:是,显式
  • 多个开放泛型:是,显式
  • 通用逆变:是,隐式

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

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
潇烟暮雨 2025-01-04 03:39:29

实际上有大量的 IoC 框架。似乎每个程序员都会在其职业生涯的某个阶段尝试编写一个程序。也许不是为了发布它,而是为了了解其内部运作方式。

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

其他一些框架:

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:

烈酒灼喉 2025-01-04 03:39:29

好吧,在查看了迄今为止我发现的最佳比较后,我发现的是:

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

我感兴趣的一点是,人们对于使用过 DI/IoC 框架并且喜欢/不喜欢它的人来说,StructureMap 似乎名列前茅。

另外从民意调查来看,似乎 Castle.WindsorStructureMap 似乎最受欢迎。

有趣的是, UnitySpring.Net 似乎是最流行的选择,但最不受欢迎。 (我出于懒惰(以及 Microsoft 徽章/支持)而考虑使用 Unity,但现在我将更仔细地研究 Castle Windsor 和 StructureMap。)

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

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

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.

小忆控 2025-01-04 03:39:29

请参阅 google 代码上的 net-ioc-frameworks 比较,包括 linfu 和在我撰写本文时,spring.net 不在您的列表中。

我使用 spring.net:它有很多功能(aop、库、docu...),并且在 dotnet 和 java 世界中拥有很多使用它的经验。这些功能是模块化的,因此您不必采用所有功能。这些功能是常见问题的抽象,例如数据库抽象、日志记录抽象。然而,进行和调试 IoC 配置很困难。

从我到目前为止所读到的内容来看:如果我必须为小型或中型项目选择 h,我会使用 ninject,因为 ioc 配置已完成并且可以在 c# 中进行调试。但我还没有使用过它。对于大型模块化系统,由于抽象库,我会继续使用 spring.net。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文