Quels sont les avantages et les inconvénients de l'utilisation de Enterprise Library Unity par rapport aux autres conteneurs IoC (Windsor, Spring.Net, Autofac ..)?
Quels sont les avantages et les inconvénients de l'utilisation de Enterprise Library Unity par rapport aux autres conteneurs IoC (Windsor, Spring.Net, Autofac ..)?
Réponses:
Je prépare une présentation pour un groupe d'utilisateurs. En tant que tel, je viens de passer par un tas d'entre eux. À savoir: AutoFac, MEF, Ninject, Spring.Net, StructureMap, Unity et Windsor.
Je voulais montrer le cas à 90% (injection de constructeur, qui est principalement ce pour quoi les gens utilisent un CIO de toute façon). Vous pouvez consulter la solution ici (VS2008)
En tant que tel, il existe quelques différences clés:
Chacun d'eux a également d'autres fonctionnalités (certains ont AOP et de meilleurs gizmos, mais en général, tout ce que je veux qu'un IOC fasse, c'est créer et récupérer des objets pour moi)
Remarque: les différences entre les différentes récupérations d'objets de bibliothèques peuvent être annulées en utilisant CommonServiceLocator: http://www.codeplex.com/CommonServiceLocator
Cela nous laisse avec l'initialisation, qui se fait de deux manières: via le code ou via la configuration XML (app.config / web.config / custom.config). Certains prennent en charge les deux, certains n'en supportent qu'un. Je devrais noter: certains utilisent des attributs pour aider l'IoC.
Voici donc mon évaluation des différences:
Initialisation du code uniquement (avec attributs). J'espère que vous aimez les lambdas. Le code d'initialisation ressemble à ceci:
IKernel kernel = new StandardKernel(
new InlineModule(
x => x.Bind<ICustomerRepository>().To<CustomerRepository>(),
x => x.Bind<ICustomerService>().To<CustomerService>(),
x => x.Bind<Form1>().ToSelf()
));
Code d'initialisation ou XML ou attributs. La v2.5 est également très lambda'y. Dans l'ensemble, c'est l'un de mes préférés. Quelques idées très intéressantes sur la façon dont StructureMap utilise les attributs.
ObjectFactory.Initialize(x =>
{
x.UseDefaultStructureMapConfigFile = false;
x.ForRequestedType<ICustomerRepository>()
.TheDefaultIsConcreteType<CustomerRepository>()
.CacheBy(InstanceScope.Singleton);
x.ForRequestedType<ICustomerService>()
.TheDefaultIsConcreteType<CustomerService>()
.CacheBy(InstanceScope.Singleton);
x.ForConcreteType<Form1>();
});
Code d'initialisation et XML. Belle bibliothèque, mais la configuration XML est une douleur dans le cul. Grande bibliothèque pour Microsoft ou les magasins d'autoroute. L'initialisation du code est simple:
container.RegisterType<ICustomerRepository, CustomerRepository>()
.RegisterType<ICustomerService, CustomerService>();
XML seulement aussi près que je peux le dire. Mais pour la fonctionnalité, Spring.Net fait tout ce qu'un IoC peut faire sous le soleil. Mais comme le seul moyen de s'unifier est via XML, il est généralement évité par les boutiques .net. Cependant, de nombreux magasins .net / Java utilisent Spring.Net en raison de la similitude entre la version .net de Spring.Net et le projet Java Spring.
Remarque : la configuration dans le code est désormais possible avec l'introduction de Spring.NET CodeConfig .
XML et code. Comme Spring.Net, Windsor fera tout ce que vous voudrez qu'elle fasse. Windsor est probablement l'un des conteneurs IoC les plus populaires.
IWindsorContainer container = new WindsorContainer();
container.AddComponentWithLifestyle<ICustomerRepository, CustomerRepository>("CustomerRepository", LifestyleType.Singleton);
container.AddComponentWithLifestyle<ICustomerService, CustomerService>("CustomerService",LifestyleType.Singleton);
container.AddComponent<Form1>("Form1");
Peut mélanger XML et code (avec v1.2). Belle bibliothèque IoC simple. Semble faire les bases sans trop de bruit. Prend en charge les conteneurs imbriqués avec une portée locale des composants et une gestion de la durée de vie bien définie.
Voici comment vous l'initialisez:
var builder = new ContainerBuilder();
builder.Register<CustomerRepository>()
.As<ICustomerRepository>()
.ContainerScoped();
builder.Register<CustomerService>()
.As<ICustomerService>()
.ContainerScoped();
builder.Register<Form1>();
Si je devais choisir aujourd'hui: j'irais probablement avec StructureMap. Il offre le meilleur support pour les fonctionnalités du langage C # 3.0 et la plus grande flexibilité dans l'initialisation.
Remarque : Chris Brandsma a transformé sa réponse originale en un article de blog .
Pour autant que j'ai vu, ils sont à peu près les mêmes, à l'exception de quelques détails d'implémentation ici et là. Le plus grand avantage d'Unity par rapport à la concurrence est qu'il est fourni par Microsoft, il y a beaucoup d'entreprises qui ont peur des OSS.
Un inconvénient est qu'il est plutôt nouveau et qu'il peut donc y avoir des bugs que les anciens joueurs ont déjà résolus.
Cela dit, vous voudrez peut-être vérifier cela .
Ancien fil mais puisque c'est la première chose que Google m'a montré quand j'ai tapé unité vs spring.net ...
Spring fait CodeConfig maintenant si vous n'aimez pas la configuration XML
http://www.springframework.net/codeconfig/doc-latest/reference/html/
De plus, Spring est bien plus qu'un simple conteneur DI, si vous regardez la section `` Modules '' dans la documentation, le conteneur DI est le fondement de l'énorme pile de choses qu'il fait.
Corrigez-moi si je me trompe mais je pense qu'Autofac lui-même prend en charge la configuration XML comme indiqué dans ce lien: Configuration XML d'Autofac
Spring a une fonctionnalité qui permet d'injecter des paramètres au constructeur ou à la propriété en fonction du nom ou de la position du paramètre. Ceci est très utile si le paramètre ou la propriété est de type simple (par exemple un entier, un booléen). Voir l'exemple ici . Je ne pense pas que cela compense vraiment l'incapacité de Spring à faire la configuration dans le code.
Windsor peut également le faire, et peut le faire en code non config. (corrigez-moi si je me trompe, je passe simplement par ce que j'ai entendu ici).
J'aimerais savoir si Unity peut le faire.
Une chose à noter: Ninject est le seul conteneur IoC qui prend en charge les injections de dépendances contextuelles (selon leur site Web). Cependant, comme je n'ai pas d'expérience avec d'autres conteneurs IoC, je ne peux pas dire si cela tient.
Juste pour ajouter mes 2 cents, j'ai essayé à la fois StructureMap et Unity. J'ai trouvé que StructureMap était mal / mal documenté, difficile à configurer et maladroit à utiliser. De même, il ne semble pas prendre en charge les scénarios tels que les remplacements d'arguments du constructeur au moment de la résolution, ce qui était un point d'utilisation clé pour moi. Je l'ai donc laissé tomber et je suis allé avec Unity, et je l'ai fait faire ce que je voulais en environ 20 minutes.
J'utilise personnellement Unity, mais uniquement parce qu'il provient de Microsoft. Je regrette la décision pour une raison: la plus grande chose qu'il a contre elle a un gros "bogue" qui le pousse à lancer constamment des exceptions. Vous pouvez ignorer les exceptions lors du débogage. Cependant, cela ralentit énormément votre application si vous la rencontrez, car lancer une exception est une opération coûteuse. Par exemple, je "corrige" actuellement cette exception à un endroit de mon code où les exceptions d'Unity ajoutent 4 secondes supplémentaires au temps de rendu d'une page. Pour plus de détails et une solution de contournement, voir:
Unity peut-il être obligé de ne pas lancer une exception SynchronizationLockException tout le temps?