Au risque d'entrer dans le territoire de la guerre sainte, quelles sont les forces et les faiblesses de ces populaires cadres DI/IoC, et pourrait-on facilement être considéré comme le meilleur? ..:
Existe-t-il d'autres cadres DI/IoC pour C # que je n'ai pas répertoriés ici?
Dans le cadre de mon cas d'utilisation, je construis une application client WPF et une infrastructure de services WCF/SQL, une facilité d'utilisation (en particulier en termes de syntaxe claire et concise), une documentation cohérente, une bonne assistance de la communauté et des performances sont tous des facteurs importants. dans mon choix.
Les ressources et les questions en double citées semblent être obsolètes. Est-ce qu'une personne connaissant tous ces cadres peut se faire connaître et fournir un aperçu réel?
Je me rends compte que la plupart des opinions sur ce sujet risquent d'être biaisées, mais j'espère que quelqu'un a pris le temps d'étudier tous ces cadres et d'avoir au moins une comparaison généralement objective.
Je suis tout à fait disposé à faire mes propres enquêtes si cela n’a pas été fait auparavant, mais j’ai supposé que c’était quelque chose que au moins quelques personnes avaient déjà fait.
Si vous avez de l'expérience avec plus d'un conteneur DI/IoC, veuillez classer et résumer les avantages et les inconvénients de ceux-ci, merci. Ce n'est pas un exercice pour découvrir tous les petits conteneurs obscurs que les gens ont fabriqués, je cherche des comparaisons entre les frameworks populaires (et actifs).
Alors qu'une réponse complète à cette question occupe des centaines de pages de mon livre , voici un rapide tableau de comparaison sur lequel je travaille toujours:
Je suis tombé sur une autre performance comparaison (dernière mise à jour le 10 avril 2014). Il compare les éléments suivants:
Voici un résumé rapide du post:
Conclusion
Ninject est définitivement le conteneur le plus lent.
MEF, LinFu et Spring.NET sont plus rapides que Ninject, mais restent assez lents. AutoFac, Catel et Windsor viennent ensuite, suivis de StructureMap, Unity et LightCore. Un inconvénient de Spring.NET est qu’il ne peut être configuré qu’avec XML.
SimpleInjector, Hiro, Funq, Munq et Dynamo offrent les meilleures performances, ils sont extrêmement rapides. Essayez-les!
L'injecteur particulièrement simple semble être un bon choix. Il est très rapide, possède une bonne documentation et prend également en charge des scénarios avancés tels que l’interception et les décorateurs génériques.
Vous pouvez également essayer d'utiliser Common Service Selector Library et, si tout va bien, essayer plusieurs options et voir ce qui vous convient le mieux.
Quelques informations sur la bibliothèque Common Service Selector du site:
La bibliothèque fournit une abstraction sur les conteneurs IoC et les localisateurs de services. L'utilisation de la bibliothèque permet à une application d'accéder indirectement aux fonctionnalités sans recourir à des références matérielles. L'espoir est qu'en utilisant cette bibliothèque, les applications et les infrastructures tierces puissent commencer à exploiter IoC/Service Location sans se lier à une implémentation spécifique.
13.09.2011: Funq et Munq ont été ajoutés à la liste des candidats. Les graphiques ont également été mis à jour et Spring.NET a été supprimé en raison de ses performances médiocres.
04.11.2011: "ajouta Simple Injector , la performance est le meilleur de tous les concurrents".
Il suffit de lire ce grand . Blog de comparaison de conteneurs .NET DI par Philip Mat.
Il effectue des tests de comparaison de performance approfondis;
Il recommande Autofac car il est petit, rapide et facile à utiliser ... Je suis d’accord. Il apparaît que nité et Ninject sont les plus lents dans ses tests.
Avertissement: Début 2015, il existe une excellente comparaison des fonctionnalités de IoC Container de Jimmy Bogard , voici un résumé:
Conteneurs comparés:
Le scénario est le suivant: j'ai une interface, IMediator, dans laquelle je peux envoyer une seule demande/réponse ou une notification à plusieurs destinataires:
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;
}
J'ai ensuite créé un ensemble de base de demandes/réponses/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 { }
Je souhaitais examiner quelques points concernant le support des conteneurs pour génériques:
Configuration pour la variance générique (enregistrement des gestionnaires pour INotification de base/création de pipelines de demandes) Mes gestionnaires sont assez simples, ils sortent simplement vers la 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();
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);
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);
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<>));
});
});
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<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
En fait, il y a des tonnes de frameworks IoC. Il semble que tous les programmeurs essaient d’en écrire un à un moment donné de leur carrière. Peut-être pas pour le publier, mais pour apprendre le fonctionnement interne.
Personnellement, je préfère l'autofac car il est assez flexible et que la syntaxe me convient (bien que je déteste vraiment que toutes les méthodes de registre soient des méthodes d'extension).
Quelques autres cadres:
Après avoir regardé autour de moi, la meilleure comparaison que j'ai trouvée jusqu'à présent est la suivante:
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
C'était un sondage réalisé en mars 2010.
Un des points qui m’intéresse, c’est que les personnes qui ont utilisé un framework DI/IoC et l’ont aimé/n’ont pas aimé, StructureMap semble sortir du lot.
Toujours d'après le sondage, il semble que Castle.Windsor et StructureMap semblent être les plus favorisés.
Fait intéressant, nité et Spring.Net semblent être les options populaires qui sont le plus généralement détestées. (J'envisageais Unity par paresse (et badge/support Microsoft), mais je regarderai de plus près maintenant Castle Windsor et StructureMap.)
Bien sûr, cela ne s'applique probablement pas à Unity 2.0, publié en mai 2010.
Espérons que quelqu'un d'autre puisse fournir une comparaison basée sur l'expérience directe.
Voir pour une comparaison de net-ioc-frameworks sur le code de Google incluant linfu et spring.net qui ne figurent pas sur votre liste pendant que j’écris ce texte.
J'ai travaillé avec spring.net: il a de nombreuses fonctionnalités (aop, bibliothèques, docu, ...) et possède une grande expérience dans le domaine de la dotnet et du monde Java. Les fonctionnalités sont modulaires, vous n’avez donc pas besoin de toutes les fonctionnalités. Les fonctionnalités sont des abstractions de problèmes courants tels que l'absorption de la base de données, l'abstraction de la journalisation. Cependant, il est difficile de faire et de déboguer la configuration IoC.
D'après ce que j'ai lu jusqu'à présent: Si je devais choisir un projet de taille petite ou moyenne, j'utiliserais ninject puisque la configuration d'ioc est terminée et peut être déboguée en c #. Mais je n'ai pas encore travaillé avec. pour les grands systèmes modulaires, je resterais avec spring.net à cause des bibliothèques d'abstraction.