it-swarm.com.de

Wie vergleichen sich die wichtigsten C # DI / IoC-Frameworks?

Was sind die Stärken und Schwächen dieser populären DI/IoC-Frameworks, und kann man leicht als das beste angesehen werden? ..:

  • Ninject
  • Einheit
  • Schloss.Windsor
  • Autofac
  • StructureMap

Gibt es andere DI/IoC-Frameworks für C #, die ich hier nicht aufgeführt habe?

Im Zusammenhang mit meinem Anwendungsfall baue ich eine Client-WPF-App und eine WCF/SQL-Dienstinfrastruktur auf. Benutzerfreundlichkeit (insbesondere in Bezug auf klare und prägnante Syntax), konsistente Dokumentation, gute Community-Unterstützung und Leistung sind wichtige Faktoren in meiner Wahl.

Aktualisieren:

Die genannten Ressourcen und doppelten Fragen scheinen veraltet zu sein. Kann jemand mit Kenntnissen über all diese Rahmenbedingungen einen echten Einblick gewähren?

Mir ist klar, dass die meisten Meinungen zu diesem Thema voreingenommen sein dürften, aber ich hoffe, dass sich jemand die Zeit genommen hat, all diese Rahmenbedingungen zu studieren und zumindest einen allgemein objektiven Vergleich anzustellen.

Ich bin durchaus bereit, meine eigenen Nachforschungen anzustellen, wenn dies noch nicht geschehen ist, aber ich nahm an, dass dies etwas war, was zumindest einige Leute bereits getan hatten.

Zweites Update:

Wenn Sie Erfahrung mit mehr als einem DI/IoC-Container haben, ordnen Sie die Vor- und Nachteile dieser Container ein und fassen Sie sie zusammen. Vielen Dank. Dies ist keine Übung, um all die obskuren kleinen Container zu entdecken, die die Leute gemacht haben. Ich suche nach Vergleichen zwischen den populären (und aktiven) Frameworks.

295
ocodo

Während eine umfassende Antwort auf diese Frage Hunderte von Seiten von meinem Buch einnimmt, ist hier eine kurze Vergleichstabelle, an der ich noch arbeite:

A table explaining difference between several DICs

220
Mark Seemann

Ich bin auf eine andere Leistung gestoßen Vergleich (letzte Aktualisierung am 10. April 2014). Es vergleicht Folgendes:

Hier ist eine kurze Zusammenfassung des Beitrags:

Fazit

Ninject ist definitiv der langsamste Container.

MEF, LinFu und Spring.NET sind schneller als Ninject, aber immer noch ziemlich langsam. Als nächstes folgen AutoFac, Catel und Windsor, gefolgt von StructureMap, Unity und LightCore. Ein Nachteil von Spring.NET ist, dass es nur mit XML konfiguriert werden kann.

SimpleInjector, Hiro, Funq, Munq und Dynamo bieten die beste Leistung und sind extrem schnell. Probieren Sie es aus!

Besonders Simple Injector scheint eine gute Wahl zu sein. Es ist sehr schnell, hat eine gute Dokumentation und unterstützt auch fortgeschrittene Szenarien wie Interception und generische Decorators.

Sie können auch die Common Service Selector Library verwenden und hoffentlich mehrere Optionen ausprobieren, um herauszufinden, welche für Sie am besten geeignet sind.

Einige Informationen zur Common Service Selector Library auf der Website:

Die Bibliothek bietet eine Abstraktion über IoC-Container und Service-Locators. Durch die Verwendung der Bibliothek kann eine Anwendung indirekt auf die Funktionen zugreifen, ohne sich auf harte Referenzen verlassen zu müssen. Mit dieser Bibliothek können Anwendungen und Frameworks von Drittanbietern IoC/Service Location nutzen, ohne sich auf eine bestimmte Implementierung festlegen zu müssen.

Aktualisieren

13.09.2011: Funq und Munq wurden der Teilnehmerliste hinzugefügt. Die Diagramme wurden ebenfalls aktualisiert und Spring.NET wurde aufgrund der schlechten Leistung entfernt.

04.11.2011: "hinzugefügt Simple Injector , die Leistung ist die beste aller Teilnehmer".

110
Pranav Shah

Lies einfach diesen tollen . Net DI Container Vergleichsblog von Philip Mat.

Er führt einige gründliche Leistungsvergleichstests durch.

Er empfiehlt Autofac , da es klein, schnell und einfach zu bedienen ist ... Ich stimme zu. Es scheint, dass Einheit und Ninject in seinen Tests am langsamsten sind.

48
brodie

Haftungsausschluss: Ab Anfang 2015 gibt es einen großartigen Vergleich der Funktionen von IoC-Containern von Jimmy Bogard , hier eine Zusammenfassung:

Verglichene Container:

  • Autofac
  • Ninject
  • Einfacher Injektor
  • StructureMap
  • Einheit
  • Windsor

Das Szenario ist das folgende: Ich habe eine Schnittstelle, IMediator, in der ich eine einzelne Anfrage/Antwort oder eine Benachrichtigung an mehrere Empfänger senden kann:

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

Ich habe dann einen Basissatz von Anfragen/Antworten/Benachrichtigungen erstellt:

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

Ich war daran interessiert, einige Dinge in Bezug auf die Containerunterstützung für Generika zu untersuchen:

  • Setup für Open Generics (IRequestHandler <,> einfach registrieren)
  • Setup für mehrere Registrierungen von Open Generics (zwei oder mehr INotificationHandler)

Einrichtung für generische Varianz (Registrieren von Handlern für die Basis-INotification/Erstellen von Request-Pipelines) Meine Handler sind ziemlich einfach und werden nur auf der Konsole ausgegeben:

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();
  • Offene Generika: Ja, implizit
  • Mehrere offene Generika: Ja, implizit
  • Allgemeine Zuwiderhandlung: ja, ausdrücklich

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);
  • Offene Generika: Ja, implizit
  • Mehrere offene Generika: Ja, implizit
  • Allgemeine Zuwiderhandlung: Ja, mit benutzerdefinierten Erweiterungen

Einfacher Injektor

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);
  • Offene Generika: ja, ausdrücklich
  • Mehrere offene Generika: ja, ausdrücklich
  • Generische Kontravarianz: Ja, implizit (mit 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<>));
    });
});
  • Offene Generika: ja, ausdrücklich
  • Mehrere offene Generika: ja, ausdrücklich
  • Generische Kontravarianz: Ja, implizit

Einheit

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;
}
  • Offene Generika: Ja, implizit
  • Mehrere offene Generika: Ja, mit benutzerdefinierter Erweiterung
  • Generische Kontravarianz: 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());
  • Offene Generika: Ja, implizit
  • Mehrere offene Generika: Ja, implizit
  • Allgemeine Zuwiderhandlung: Ja, mit benutzerdefinierter Erweiterung
29
stratovarius

Tatsächlich gibt es Tonnen von IoC-Frameworks. Es scheint, als würde jeder Programmierer irgendwann in seiner Karriere versuchen, eine zu schreiben. Vielleicht nicht, um es zu veröffentlichen, sondern um das Innenleben zu lernen.

Ich persönlich bevorzuge Autofac, da es ziemlich flexibel ist und eine Syntax hat, die zu mir passt (obwohl ich es wirklich hasse, dass alle Registermethoden Erweiterungsmethoden sind).

Einige andere Frameworks:

20
jgauffin

Nun, nachdem ich mich umgesehen habe, ist der beste Vergleich, den ich bisher gefunden habe:

Es war eine Umfrage im März 2010.

Ein Punkt von Interesse für mich ist, dass Leute, die ein DI/IoC-Framework verwendet haben und es mochten/nicht mochten, StructureMap anscheinend die Nase vorn hat.

Auch aus der Umfrage geht hervor, dass Castle.Windsor und StructureMap am meisten bevorzugt zu sein scheinen.

Interessanterweise scheinen nity und Spring.Net die beliebtesten Optionen zu sein, die im Allgemeinen nicht gemocht werden. (Ich habe Unity aus Faulheit (und Microsoft-Logo/Support) in Betracht gezogen, aber ich werde jetzt Castle Windsor und StructureMap näher betrachten.)

Natürlich trifft dies wahrscheinlich (?) Nicht auf Unity 2.0 zu, das im Mai 2010 veröffentlicht wurde.

Hoffentlich kann jemand anderes einen Vergleich liefern, der auf direkten Erfahrungen basiert.

6
ocodo

Sehen Sie für einen Vergleich von Net-Ioc-Frameworks auf Google Code einschließlich linfu und spring.net, die nicht auf Ihrer Liste sind, während ich diesen Text schreibe.

Ich habe mit spring.net gearbeitet: Es hat viele Funktionen (aop, Libraries, docu, ...) und es gibt viel Erfahrung damit im Dotnet und in der Java-Welt. Die Funktionen sind modularisiert, sodass Sie nicht alle Funktionen nutzen müssen. Bei den Features handelt es sich um Abstraktionen häufig auftretender Probleme wie Datenbankabstraktion, Protokollierungsabstraktion. Es ist jedoch schwierig, die IoC-Konfiguration durchzuführen und zu debuggen.

Nach allem, was ich bisher gelesen habe: Wenn ich mich für ein kleines oder mittleres Projekt entscheiden müsste, würde ich ninject verwenden, da die ioc-Konfiguration in c # abgeschlossen und debuggbar ist. Aber ich habe noch nicht damit gearbeitet. für große modulare systeme würde ich wegen abstraktionsbibliotheken bei spring.net bleiben.

5
k3b