web-dev-qa-db-ja.com

主要なC#DI / IoCフレームワークはどのように比較されますか?

聖戦領域に足を踏み入れる危険があるので、これらの人気のあるDI/IoCフレームワークの長所と短所は何ですか。 ..:

  • Ninject
  • 団結
  • Castle.Windsor
  • Autofac
  • StructureMap

ここに記載していないC#用のDI/IoCフレームワークは他にありますか?

ユースケースのコンテキストでは、クライアントWPFアプリを構築し、WCF/SQLサービスインフラストラクチャ、使いやすさ(特に明確で簡潔な構文)、一貫性のあるドキュメント、優れたコミュニティサポート、パフォーマンスがすべて重要な要素です私の選択で。

更新:

引用されているリソースと重複する質問は古くなっているように見えますが、これらすべてのフレームワークの知識を持つ人が前に出て、本当の洞察を提供できますか?

このテーマに関する意見のほとんどは偏っている可能性が高いと思いますが、誰かがこれらのフレームワークをすべて研究するために時間を割いて、少なくとも一般的に客観的な比較ができることを望んでいます。

これが以前に行われていなかった場合、私は自分の調査をすることをかなり喜んでいますが、私はこれが少なくとも少数の人々がすでに行ったことであると思いました。

2回目の更新:

複数のDI/IoCコンテナーの使用経験がある場合は、それらの長所と短所をランク付けして要約してください、ありがとうございます。これは、人々が作った不明瞭な小さなコンテナをすべて発見するための練習ではありません。人気のある(そしてアクティブな)フレームワークの比較を探しています。

294
ocodo

この質問に対する包括的な答えは my book の何百ページもかかりますが、今取り組んでいる簡単な比較表を以下に示します。

A table explaining difference between several DICs

220
Mark Seemann

私は別のパフォーマンスに出会いました 比較 (2014年4月10日の最新アップデート)。以下を比較します。

投稿からの簡単な要約は次のとおりです。

結論

Ninjectは間違いなく最も遅いコンテナです。

MEF、LinFu、およびSpring.NETはNinjectより高速ですが、それでもかなり低速です。次にAutoFac、Catel、Windsorが続き、StructureMap、Unity、LightCoreが続きます。 Spring.NETの欠点は、XMLでのみ構成できることです。

SimpleInjector、Hiro、Funq、Munq、およびDynamoは最高のパフォーマンスを提供し、非常に高速です。それらを試してみてください!

特にSimple Injectorは良い選択のようです。非常に高速で、優れたドキュメントがあり、インターセプトや汎用デコレータなどの高度なシナリオもサポートしています。

Common Service Selector Library を使用してみて、できれば複数のオプションを試して、最適なものを確認してください。

サイトからのCommon Service Selectorライブラリに関する情報:

このライブラリは、IoCコンテナーとサービスロケーターの抽象化を提供します。ライブラリを使用すると、アプリケーションはハード参照に依存せずに間接的に機能にアクセスできます。このライブラリを使用すると、サードパーティのアプリケーションとフレームワークが特定の実装に縛られることなく、IoC/Service Locationを活用し始めることができます。

更新

13.09.2011:Funq および Munq が競技者のリストに追加されました。グラフも更新され、Spring.NETはパフォーマンスが低いため削除されました。

04.11.2011: " Simple Injector を追加、パフォーマンスはすべての競技者の中で最高です"。

110
Pranav Shah

Philip Matによるこの素晴らしい 。Net DIコンテナー比較ブログ を読んでください。

彼はいくつかの徹底的なパフォーマンス比較テストを行います。

彼は Autofac をお勧めします。それは小さく、高速で、使いやすいからです...同意します。 nity および Ninject は、彼のテストで最も遅いようです。

48
brodie

免責事項:2015年初頭の時点で、IoC ContainerfeaturesJimmy Bogard から、ここに要約があります:

比較されたコンテナ:

  • 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 <、>の簡単な登録)
  • オープンジェネリックの複数の登録のセットアップ(2つ以上の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

ウィンザー

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • オープンジェネリック:はい、暗黙的に
  • 複数のオープンジェネリック:はい、暗黙的に
  • 一般的な矛盾:はい、ユーザーが作成した拡張機能を使用
29
stratovarius

実際、多くのIoCフレームワークがあります。すべてのプログラマーがキャリアのある時点で1つを書き込もうとしているようです。それを公表するのではなく、内部の仕組みを学ぶためかもしれません。

Autofacは非常に柔軟で、自分に合った構文を持っているため、個人的にはautofacを好みます(すべての登録メソッドが拡張メソッドであることは本当に嫌いです)。

他のいくつかのフレームワーク:

20
jgauffin

さて、私がこれまでに見つけた最高の比較を見て回った後:

2010年3月に行われた投票でした。

私が興味を持っている点の1つは、DI/IoCフレームワークを使用し、それが好き/嫌いだった人々が、StructureMapがトップに登場するように見えることです。

世論調査からも、 Castle.Windsor および StructureMap が最も好まれているようです。

興味深いことに、 nity および Spring.Net は、最も一般的に嫌われている人気のあるオプションのようです。 (私はUnityを怠of(およびMicrosoftバッジ/サポート)から除外することを検討していましたが、Castle WindsorとStructureMapを今より詳しく見ていきます。)

もちろん、これはおそらく2010年5月にリリースされたUnity 2.0には適用されません(?)。

他の誰かが直接の経験に基づいて比較を提供できることを願っています。

6
ocodo

google-codeのnet-ioc-frameworks の比較については、このテキストを書いている間にリストにないlinfuとspring.netを参照してください。

私はspring.netを使用しました。多くの機能(aop、library、docu、...)があり、ドットネットとJavaの世界で多くの経験があります。機能はモジュール化されているため、すべての機能を使用する必要はありません。機能は、databaseabstraction、loggingabstractionなどの一般的な問題の抽象化です。ただし、IoC構成の実行とデバッグは困難です。

これまで読んだことから:中小規模のプロジェクトを選択する必要がある場合、ioc構成が行われ、C#でデバッグできるため、ninjectを使用します。しかし、私はまだそれに取り組んでいません。大規模なモジュラーシステムの場合、抽象化ライブラリのため、spring.netにとどまります。

5
k3b