¿Cómo se comparan los marcos principales de C# DI/IoC? [cerrado]


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

  • Ninject
  • Unidad
  • [3] Castillo.Windsor
  • Autofac
  • StructureMap

¿Hay otros Frameworks DI/IoC para C# que no he enumerado aquí?

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

Actualización:

Los recursos y las preguntas duplicadas citadas parecen estar desactualizadas, ¿puede alguien con conocimiento de todos estos marcos presentarse y proporcionar alguna idea real?

Me doy cuenta de que la mayoría de la opinión sobre este tema es probable que sea sesgada, pero espero que alguien se haya tomado el tiempo para estudiar todos estos marcos y tienen 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 resuma los pros y los contras de esos, gracias. Esto no es un ejercicio para descubrir todos los pequeños contenedores oscuros que la gente ha hecho, Estoy buscando comparaciones entre los marcos populares (y activos).

Author: Mark Seemann, 2011-01-03

7 answers

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

Una tabla que explica la diferencia entre varios DIC

 209
Author: Mark Seemann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 09:23:33

Me encontré con otra comparación de rendimiento (última actualización 10 abril 2014). Se compara lo siguiente:

Aquí hay un breve resumen del post:

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 así bastante lento. AutoFac, Catel y Windsor vienen a continuación, seguidos por StructureMap, Unidad y LightCore. Una desventaja de Spring.NET es, que sólo puede ser configurado con XML.

SimpleInjector, Hiro, Funq, Munq y Dynamo ofrecen lo mejor rendimiento, son extremadamente rápidos. ¡Dales una oportunidad!

Inyector especialmente simple parece ser una buena opción. Es muy rápido, tiene una buena documentación y también soporta escenarios avanzados como la interceptación y decoradores genéricos.

También puede intentar usar la Biblioteca de Selectores de Servicios Comunes y con suerte probar varias opciones y ver lo que funciona mejor para usted.

Alguna información sobre la Biblioteca de Selectores de Servicios Comunes del sitio:

La biblioteca proporciona una abstracción sobre contenedores IoC y servicio localizador. El uso de la biblioteca permite a una aplicación acceder indirectamente las capacidades sin depender de referencias duras. La esperanza es que con esta biblioteca, las aplicaciones y marcos de trabajo de terceros pueden comenzar para aprovechar la Ubicación del CoI/Servicio sin atarse a sí mismos a un aplicación específica.

Actualización

13.09.2011: Funq y Munq se añadieron a la lista de concursantes. También se actualizaron los gráficos, y Spring.NET fue eliminado debido a su pobre rendimiento.

04.11.2011: "añadido Simple Inyector , el rendimiento es el mejor de todos los concursantes".

 109
Author: Pranav Shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-28 05:29:38

Acaba de leer este gran . net DI container comparison blog por Philip Mat.

Hace algunas pruebas exhaustivas de comparación de rendimiento en;

Recomienda Autofac ya que es pequeño, rápido y fácil de usar ... Coincido. Parece que Unidad y Ninject son los más lentos en sus pruebas.

 47
Author: brodie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-15 15:25:08

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

Contenedores comparados:

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

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

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

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

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

Estaba interesado en mirar algunas cosas con respecto al soporte de contenedores para genéricos:

  • Configuración para genéricos abiertos (registrando IRequestHandler fácilmente)
  • Configuración para registros múltiples de genéricos abiertos (dos o más INotificationHandlers)

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

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

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

Inyector simple

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);
  • Genéricos abiertos: sí, explícitamente
  • Múltiples genéricos 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<Ping>();
        scanner.AssemblyContainingType<IMediator>();
        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 genéricos abiertos: sí, explícitamente
  • Contravariancia 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
  • Múltiples genéricos abiertos: sí, con extensión construida por el usuario
  • Contravariancia genérica: 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());
  • Genéricos abiertos: sí, implícitamente
  • Múltiples genéricos abiertos: sí, implícitamente
  • Contravarianza genérica: sí, con extensión construida por el usuario
 28
Author: stratovarius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-12 18:57:29

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

Personalmente prefiero autofac ya que es bastante flexible y tiene una sintaxis que me conviene (aunque realmente odio que todos los métodos de registro sean métodos de extensión).

Algún otro marcos:

 20
Author: jgauffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-29 15:10:03

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 las personas que han utilizado un marco DI / IoC y les gustó/no les gustó, StructureMap parece salir superior.

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

Curiosamente, Unidad y Spring.Net parecen ser las opciones populares que generalmente no les gustan. (Estaba considerando Unity por pereza (y Microsoft badge / support), pero ahora estaré mirando más de cerca Castle Windsor y StructureMap.)

Por supuesto, esto probablemente (?) no se aplica a Unity 2.0 que fue lanzado en mayo de 2010.

Esperemos que alguien más pueda proporcionar una comparación basada en la experiencia directa.

 6
Author: ocodo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-03 10:09:56

Ver para una comparación de net-ioc-frameworks en google code 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, bibliotecas, docu,...) y hay mucha experiencia con él en dotnet y el mundo java. Las características están modularizadas para que no tenga que tomar todas las características. Las características son abstracciones de problemas comunes como databaseabstraction, loggingabstraction. sin embargo es difícil hacer y depurar la configuración del IoC.

De lo que he leído hasta ahora: Si tuviera que elegir un proyecto pequeño o mediano, usaría ninject ya que la configuración de ioc está hecha y se puede depurar en c#. Pero aún no he trabajado con él. para el sistema modular grande me quedaría con spring.net debido a la abstracción-bibliotecas.

 5
Author: k3b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-03 05:35:06