A rischio di entrare nel territorio della guerra santa, quali sono i punti di forza e di debolezza di questi famosi framework DI / IoC e si potrebbe facilmente essere considerati i migliori? ..:
Ci sono altri DI / IoC Framework per C # che non ho elencato qui?
Nel contesto del mio caso d’uso, sto costruendo un’app WPF client e un’infrastruttura di servizi WCF / SQL, facilità d’uso (soprattutto in termini di syntax chiara e concisa), documentazione coerente, buon supporto della comunità e prestazioni sono tutti fattori importanti nella mia scelta
Le risorse e le domande duplicate citate sembrano essere obsolete, qualcuno con conoscenza di tutti questi quadri può farsi avanti e fornire qualche intuizione reale?
Mi rendo conto che la maggior parte delle opinioni su questo argomento è tendenzialmente distorta, ma spero che qualcuno abbia avuto il tempo di studiare tutti questi quadri e di avere almeno un confronto generalmente objective.
Sono abbastanza disposto a fare le mie indagini se questo non è stato fatto prima, ma ho pensato che fosse qualcosa che almeno alcune persone avevano già fatto.
Se hai esperienza con più di un contenitore DI / IoC, per favore classifica e riassumi i pro e i contro di quelli, grazie. Questo non è un esercizio per scoprire tutti i piccoli contenitori oscuri che le persone hanno fatto, sto cercando dei confronti tra le strutture popolari (e attive).
Mentre una risposta esauriente a questa domanda occupa centinaia di pagine del mio libro , ecco una rapida tabella di confronto su cui sto ancora lavorando:
Mi sono imbattuto in un altro confronto dei risultati (ultimo aggiornamento il 10 aprile 2014). Confronta i seguenti:
Ecco un breve riassunto dal post:
Conclusione
Ninject è sicuramente il contenitore più lento.
MEF, LinFu e Spring.NET sono più veloci di Ninject, ma ancora piuttosto lenti. AutoFac, Catel e Windsor vengono dopo, seguito da StructureMap, Unity e LightCore. Uno svantaggio di Spring.NET è che può essere configurato solo con XML.
SimpleInjector, Hiro, Funq, Munq e Dynamo offrono le migliori prestazioni, sono estremamente veloci. Provali!
Iniettore particolarmente semplice sembra essere una buona scelta. È molto veloce, ha una buona documentazione e supporta anche scenari avanzati come l’intercettazione e i decoratori generici.
Puoi anche provare a usare la Common Selector Library e sperare di provare più opzioni e vedere cosa funziona meglio per te.
Alcune informazioni su Common Service Selector Library dal sito:
La libreria fornisce un’astrazione su contenitori IoC e localizzatori di servizi. L’utilizzo della libreria consente a un’applicazione di accedere indirettamente alle funzionalità senza fare affidamento su riferimenti rigidi. La speranza è che usando questa libreria, le applicazioni e i framework di terze parti possano iniziare a sfruttare IoC / Service Location senza limitarsi a un’implementazione specifica.
13.09.2011: Funq e Munq sono stati aggiunti all’elenco dei concorrenti. Anche i grafici sono stati aggiornati e Spring.NET è stato rimosso a causa delle scarse prestazioni.
04.11.2011: “Aggiunto Simple Injector , la performance è la migliore di tutti i concorrenti”.
Basta leggere questo fantastico blog di confronto dei contenitori .Net di Philip Mat.
Effettua alcuni accurati test di confronto delle prestazioni;
Raccomanda Autofac in quanto è piccolo, veloce e facile da usare … Sono d’accordo. Sembra che Unity e Ninject siano i più lenti nei suoi test.
Disclaimer: all’inizio del 2015, c’è un ottimo confronto tra le caratteristiche del contenitore IoC di Jimmy Bogard , ecco un riassunto:
Contenitori confrontati:
Lo scenario è questo: ho un’interfaccia, IMediator, nella quale posso inviare una singola richiesta / risposta o una notifica a più destinatari:
public interface IMediator { TResponse Send(IRequest request); Task SendAsync (IAsyncRequest request); void Publish(TNotification notification) where TNotification : INotification; Task PublishAsync (TNotification notification) where TNotification : IAsyncNotification; }
Ho quindi creato una serie di richieste / risposte / notifiche:
public class Ping : IRequest { public string Message { get; set; } } public class Pong { public string Message { get; set; } } public class PingAsync : IAsyncRequest { public string Message { get; set; } } public class Pinged : INotification { } public class PingedAsync : IAsyncNotification { }
Mi interessava osservare alcune cose riguardo al supporto dei contenitori per i generici:
Setup per varianza generica (registrazione dei gestori per l’inizializzazione di base / creazione di pipeline di richieste) I miei gestori sono piuttosto semplici, vengono semplicemente inviati alla console:
public class PingHandler : IRequestHandler { /* Impl */ } public class PingAsyncHandler : IAsyncRequestHandler { /* Impl */ } public class PingedHandler : INotificationHandler { /* Impl */ } public class PingedAlsoHandler : INotificationHandler { /* Impl */ } public class GenericHandler : INotificationHandler { /* Impl */ } public class PingedAsyncHandler : IAsyncNotificationHandler { /* Impl */ } public class PingedAlsoAsyncHandler : IAsyncNotificationHandler { /* 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(); kernel.Bind(scan => scan.FromAssemblyContaining() .SelectAllClasses() .BindDefaultInterface()); kernel.Bind(scan => scan.FromAssemblyContaining() .SelectAllClasses() .BindAllInterfaces()); kernel.Bind().ToConstant(Console.Out);
Iniettore semplice
var container = new Container(); var assemblies = GetAssemblies().ToArray(); container.Register(); container.Register(typeof(IRequestHandler<,>), assemblies); container.Register(typeof(IAsyncRequestHandler<,>), assemblies); container.RegisterCollection(typeof(INotificationHandler<>), assemblies); container.RegisterCollection(typeof(IAsyncNotificationHandler<>), assemblies);
StructureMap
var container = new Container(cfg => { cfg.Scan(scanner => { scanner.AssemblyContainingType(); scanner.AssemblyContainingType(); scanner.WithDefaultConventions(); scanner.AddAllTypesOf(typeof(IRequestHandler<,>)); scanner.AddAllTypesOf(typeof(IAsyncRequestHandler<,>)); scanner.AddAllTypesOf(typeof(INotificationHandler<>)); scanner.AddAllTypesOf(typeof(IAsyncNotificationHandler<>)); }); });
Unità
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; }
Windsor
var container = new WindsorContainer(); container.Register(Classes.FromAssemblyContaining().Pick().WithServiceAllInterfaces()); container.Register(Classes.FromAssemblyContaining().Pick().WithServiceAllInterfaces()); container.Kernel.AddHandlersFilter(new ContravariantFilter());
In realtà ci sono tonnellate di strutture IoC. Sembra che ogni programmatore cerchi di scriverne uno ad un certo punto della propria carriera. Forse non pubblicarlo, ma per imparare il funzionamento interno.
Personalmente preferisco autofac perché è abbastanza flessibile e ha una syntax che mi si addice (anche se odio davvero che tutti i metodi di registrazione sono metodi di estensione).
Alcuni altri quadri:
Bene, dopo aver guardato intorno il miglior confronto che ho trovato finora è:
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
Era un sondaggio fatto a marzo 2010.
Un punto di interesse per me è che le persone che hanno utilizzato un DI / IoC Framework e l’hanno apprezzato / non l’hanno apprezzato, StructureMap sembra uscito in cima.
Anche dal sondaggio, sembra che Castle.Windsor e StructureMap sembrano essere i più favoriti.
È interessante notare che Unity e Spring.Net sembrano essere le opzioni popolari che generalmente non piacciono. (Stavo considerando Unity per pigrizia (e badge / supporto Microsoft), ma guarderò più da vicino Castle Windsor e StructureMap ora.)
Naturalmente questo probabilmente (?) Non si applica a Unity 2.0 che è stato rilasciato nel maggio 2010.
Speriamo che qualcun altro possa fornire un confronto basato sull’esperienza diretta.
Vedi per un confronto di framework net-ioc su google code incluso linfu e spring.net che non sono nella tua lista mentre scrivo questo testo.
Ho lavorato con spring.net: ha molte caratteristiche (aop, librerie, docu, …) e c’è molta esperienza con esso nel dotnet e nel mondo java. Le funzionalità sono modularizzate in modo da non dover prendere tutte le funzionalità. Le funzionalità sono astrazioni di problemi comuni come databaseabstraction, loggingabstraction. tuttavia è difficile da fare ed eseguire il debug della configurazione IoC.
Da quello che ho letto finora: Se dovessi scegliereh per un progetto piccolo o medio, userei ninject da quando la configurazione di ioc è terminata e debuggibile in c #. Ma non ho ancora lavorato con questo. per un grande sistema modulare starei con spring.net a causa delle librerie di astrazione.