¿Cómo se comparan los principales marcos C # DI / IoC?

A riesgo de entrar en el territorio de la guerra santa, ¿cuáles son las fortalezas y debilidades de estos populares marcos DI / IoC, y podría uno fácilmente ser considerado el mejor? ..:

  • Ninject
  • Unidad
  • Castle.Windsor
  • Autofac
  • StructureMap

¿Hay alguna otra estructura DI / IoC para C # que no haya enumerado aquí?

En el contexto de mi caso de uso, estoy construyendo una aplicación WPF cliente, y una infraestructura de servicios WCF / SQL, facilidad de uso (especialmente en términos de syntax clara y concisa), documentación consistente, buen apoyo de la comunidad y rendimiento son todos factores importantes en mi elección.

Actualizar:

Los recursos y las preguntas duplicadas que se citan parecen estar desactualizados. ¿Puede alguien con conocimiento de todos estos marcos presentar y proporcionar una idea real?

Me doy cuenta de que la mayoría de las opiniones sobre este tema es probable que sean parciales, pero espero que alguien se haya tomado el tiempo para estudiar todos estos marcos y tener al menos una comparación generalmente objetiva.

Estoy dispuesto a hacer mis propias investigaciones si esto no se ha hecho antes, pero asumí que esto era algo que al menos algunas personas ya habían hecho.

Segunda actualización:

Si tiene experiencia con más de un contenedor DI / IoC, clasifique y resum los pros y contras de esos, gracias. Este no es un ejercicio para descubrir todos los pequeños recipientes oscuros que las personas han hecho, estoy buscando comparaciones entre los marcos populares (y activos).

Si bien una respuesta completa a esta pregunta ocupa cientos de páginas de mi libro , aquí hay un gráfico de comparación rápida en el que todavía estoy trabajando:

Una tabla que explica la diferencia entre varios DIC

Encontré otra comparación de rendimiento (última actualización 10 de abril de 2014). Compara lo siguiente:

  • AutoFac
  • LightCore (el sitio es alemán)
  • LinFu
  • Ninject
  • Chiquita
  • Inyector simple (el más rápido de todos los concursantes)
  • Spring.NET
  • StructureMap
  • Unidad
  • Windsor
  • Hiro

Aquí hay un resumen rápido de la publicación:

Conclusión

Ninject es definitivamente el contenedor más lento.

MEF, LinFu y Spring.NET son más rápidos que Ninject, pero aún bastante lento. AutoFac, Catel y Windsor son los siguientes, seguidos de StructureMap, Unity y LightCore. Una desventaja de Spring.NET es que solo se puede configurar con XML.

SimpleInjector, Hiro, Funq, Munq y Dynamo ofrecen el mejor rendimiento, son extremadamente rápidos. Pruébalos!

Especialmente Simple Injector parece ser una buena opción. Es muy rápido, tiene una buena documentación y también admite escenarios avanzados como la interceptación y decoradores generics.

También puede intentar usar la Biblioteca de selección de servicios comunes y, con suerte, probar varias opciones y ver qué funciona mejor para usted.

Alguna información sobre la Biblioteca del Selector de servicios comunes del sitio:

La biblioteca proporciona una abstracción sobre los contenedores de IoC y los localizadores de servicios. El uso de la biblioteca permite que una aplicación acceda indirectamente a las capacidades sin depender de referencias difíciles. La esperanza es que al usar esta biblioteca, las aplicaciones y marcos de terceros puedan comenzar a aprovechar IoC / Service Location sin atarse a una implementación específica.

Actualizar

13.09.2011: Funq y Munq se agregaron a la lista de concursantes. Los gráficos también se actualizaron y Spring.NET se eliminó debido a su bajo rendimiento.

04.11.2011: ” Inyector simple agregado, el rendimiento es el mejor de todos los concursantes”.

Acabo de leer este gran blog de comparación de contenedores DI de Philip Mat.

Él hace algunas pruebas de comparación de rendimiento a fondo en;

  • Autofac
  • StructureMap
  • Ninject
  • Unidad
  • Castle.Windsor
  • Spring.Net

Él recomienda Autofac, ya que es pequeño, rápido y fácil de usar … Estoy de acuerdo. Parece que Unity y Ninject son los más lentos en sus pruebas.

Descargo de responsabilidad: A principios de 2015, hay una gran comparación de las características del contenedor IoC de Jimmy Bogard , aquí hay un resumen:

Envases comparados:

  • Autofac
  • Ninject
  • Inyector simple
  • StructureMap
  • Unidad
  • Windsor

El escenario es el siguiente: tengo una interfaz, IMediator, en la que puedo enviar una única solicitud / respuesta o una notificación a múltiples destinatarios:

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

Luego creé un conjunto base de solicitudes / respuestas / notificaciones:

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

Estaba interesado en ver algunas cosas con respecto al soporte de contenedores para generics:

  • Configuración para generics abiertos (registrando IRequestHandler <,> fácilmente)
  • Configuración para múltiples registros de generics abiertos (dos o más INotificationHandlers)

Configuración para la varianza genérica (controladores de registro para canalizaciones de solicitud de INotification / creación de la base) Mis controladores son bastante sencillos, solo salen a la consola:

 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(); 
  • Genéricos abiertos: sí, implícitamente
  • Múltiples generics abiertos: sí, implícitamente
  • Contravarianza genérica: sí, explícitamente

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); 
  • Genéricos abiertos: sí, implícitamente
  • Múltiples generics abiertos: sí, implícitamente
  • Contravarianza genérica: sí, con extensiones creadas por el usuario

Inyector simple

 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); 
  • Genéricos abiertos: sí, explícitamente
  • Múltiples generics abiertos: sí, explícitamente
  • Contravarianza genérica: sí, implícitamente (con la actualización 3.0)

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<>)); }); }); 
  • Genéricos abiertos: sí, explícitamente
  • Múltiples generics abiertos: sí, explícitamente
  • Contravarianza genérica: sí, implícitamente

Unidad

 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; } 
  • Genéricos abiertos: sí, implícitamente
  • Varios generics abiertos: sí, con extensión creada por el usuario
  • Contravarianza genérica: derp

Windsor

 var container = new WindsorContainer(); container.Register(Classes.FromAssemblyContaining().Pick().WithServiceAllInterfaces()); container.Register(Classes.FromAssemblyContaining().Pick().WithServiceAllInterfaces()); container.Kernel.AddHandlersFilter(new ContravariantFilter()); 
  • Genéricos abiertos: sí, implícitamente
  • Múltiples generics abiertos: sí, implícitamente
  • Contravarianza genérica: sí, con la extensión creada por el usuario

En realidad, hay toneladas de frameworks de IoC. Parece que cada progtwigdor intenta escribir uno en algún momento de su carrera. Tal vez no para publicarlo, sino para aprender el funcionamiento interno.

Yo personalmente prefiero autofac ya que es bastante flexible y tiene una syntax que me satisface (aunque realmente odio que todos los métodos de registro sean métodos de extensión).

Algunos otros marcos:

Bueno, después de mirar alrededor, la mejor comparación que he encontrado hasta ahora es:

Fue una encuesta realizada en marzo de 2010.

Un punto de interés para mí es que a la gente que ha usado un Marco DI / IoC y le gustó / disgustó, StructureMap parece estar en la cima.

También de la encuesta, parece que Castle.Windsor y StructureMap parecen ser los más favorecidos.

Curiosamente, Unity y Spring.Net parecen ser las opciones populares que generalmente no son apreciadas. (Estaba considerando Unity por holgazanería (y por la insignia / soporte de Microsoft), pero ahora voy a mirar más de cerca a Castle Windsor y StructureMap.)

Por supuesto, esto probablemente (?) No se aplica a Unity 2.0 que se lanzó en mayo de 2010.

Con suerte, alguien más puede proporcionar una comparación basada en la experiencia directa.

Consulte para una comparación de net-ioc-frameworks en el código de google incluyendo linfu y spring.net que no están en su lista mientras escribo este texto.

Trabajé con spring.net: tiene muchas características (aop, libraries, docu, …) y hay mucha experiencia en dotnet y java-world. Las características están moduladas para que no tenga que tomar todas las características. Las características son abstracciones de problemas comunes como la extracción de bases de datos, la extracción de registros. sin embargo, es difícil de hacer y depurar la configuración de IoC.

Por lo que he leído hasta ahora: si tuviera que elegirh para un proyecto pequeño o mediano, usaría ninject ya que ioc-configuration está listo y se puede depurar en c #. Pero aún no he trabajado con eso. para un gran sistema modular me quedaría con spring.net debido a abstraction-libraries.