Как сравниваются основные фреймворки C# DI/IoC? [закрытый]


рискуя попасть на территорию Священной войны, каковы сильные и слабые стороны этих популярных структур DI/IoC, и можно ли легко считать их лучшими? ..:

  • Ninject
  • единство
  • замок.Виндзор
  • Autofac
  • StructureMap

есть ли другие рамки DI/IoC для C#, которые я не перечислил здесь?

в контексте моего варианта использования я создаю клиент WPF приложение и инфраструктура служб WCF / SQL, простота использования (особенно с точки зрения четкого и краткого синтаксиса), согласованная документация, хорошая поддержка сообщества и производительность-все это важные факторы в моем выборе.

обновление:

ресурсы и повторяющиеся вопросы, приведенные, кажется, устарели, может ли кто-то со знанием всех этих рамок выйти вперед и дать некоторое реальное представление?

Я понимаю, что большинство мнений по этому вопросу, вероятно, будет предвзято, но я надеюсь, что кто-то нашел время, чтобы изучить все эти рамки и иметь, по крайней мере, в целом объективное сравнение.

Я вполне готов провести свое собственное расследование, если это не было сделано раньше, но я предположил, что это было что-то, по крайней мере, несколько человек уже сделали.

Второй Обновления:

Если у вас есть опыт работы с более чем одним контейнером DI/IoC, пожалуйста, оцените и обобщите плюсы и минусы этих, спасибо. Этот это не упражнение в обнаружении всех неясных маленьких контейнеров, которые сделали люди, я ищу сравнения между популярными (и активными) фреймворками.

7 286

7 ответов:

в то время как исчерпывающий ответ на этот вопрос занимает сотни страниц моей книги, вот краткая сравнительная диаграмма, над которой я все еще работаю:

A table explaining difference between several DICs

я наткнулся на другой спектакль сравнение(последнее обновление 10 апрель 2014). Он сравнивает следующее:

вот краткое резюме из поста:

вывод

Ninject, безусловно, самый медленный контейнер.

MEF, LinFu и Spring.NET быстрее, чем Ninject, но все же хорошенький медленный. AutoFac, Catel и Windsor идут дальше, а затем StructureMap, Единство и Лайткор. Недостаток Spring.NET есть, что только может быть настроен с помощью XML.

SimpleInjector, Hiro, Funq, Munq и Динамо предлагают самое лучшее производительность, они чрезвычайно быстры. Дайте им попробовать!

особенно простой инжектор кажется хорошим выбором. Это очень быстро, имеет хороший документация, а также поддерживает расширенные сценарии, такие как перехват и общие декораторы.

вы также можете попробовать использовать Библиотека Селектора Общих Служб и, надеюсь, попробовать несколько вариантов и посмотреть, что работает лучше для вас.

некоторая информация о библиотеке селекторов общих служб с сайта:

библиотека предоставляет абстракцию над контейнерами IoC и службой локаторы. Использование библиотеки позволяет приложению получить косвенный доступ возможности без полагаться на трудном ссылки на литературу. Есть надежда, что с помощью этой библиотеки можно запускать сторонние приложения и фреймворки чтобы использовать местоположение IoC/Service, не привязывая себя к a конкретная реализация.

обновление

13.09.2011:Funq и Munq были добавлены в список участников. Диаграммы также были обновлены, и Spring.NET был удален из-за его плохого спектакль.

04.11.2011: "добавил Простой Инжектор, спектакль-лучший из всех конкурсантов".

просто читать эту великую .Чистый блог-Ди-сравнение контейнера Филипп мат.

Он делает некоторые тщательные тесты сравнения производительности;

он рекомендует Autofac как это маленький, быстрый, и легкий в использовании ... Я согласен. Оказывается, что единство и Ninject являются самыми медленными в своих тестах.

отказ от ответственности: по состоянию на начало 2015 года, есть большое сравнение контейнера МОК особенности С Джимми Богард вот резюме:

По Сравнению Контейнеров:

  • Autofac
  • Ninject
  • Простой Инжектор
  • StructureMap
  • единство
  • Виндзор

сценарий такой: у меня есть интерфейс, IMediator, в котором я может отправить один запрос/ответ или уведомление нескольким получателям:

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

затем я создал базовый набор запросов / ответов / уведомлений:

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

мне было интересно посмотреть на несколько вещей в отношении поддержки контейнеров для дженериков:

  • настройка для открытых дженериков (Регистрация IRequestHandler легко)
  • настройка для нескольких регистраций открытых дженериков (двух или более больше INotificationHandlers)

настройка для общей дисперсии (Регистрация обработчиков для базовой Инотификации/создание конвейеров запросов) Мои обработчики довольно просты, они просто выводят на консоль:

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);
  • открытые дженерики: да, неявно
  • несколько открытых дженериков: да, имплицитно
  • общая контравариантность: да, с пользовательскими расширениями

Простой Инжектор

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);
  • открытые дженерики: да, явно
  • несколько открытых дженериков: да, явно
  • универсальный контравариантность: да, неявно (с обновлением 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<>));
    });
});
  • открытые дженерики: да, явно
  • несколько открытых дженериков: да, явно
  • общая контравариантность: да, неявно

единство

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;
}
  • открытые дженерики: да, неявно
  • несколько открытых дженериков: да, с пользовательским расширением
  • Generic контравариантность: сумасшедший

Виндзор

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • открытые дженерики: да, неявно
  • несколько открытых дженериков: да, имплицитно
  • общая контравариантность: да, с пользовательским расширением

на самом деле есть куча рамок МОК. Кажется, что каждый программист пытается написать один в какой-то момент своей карьеры. Может быть, не публиковать его, а изучать внутреннюю работу.

Я лично предпочитаю autofac, так как он довольно гибкий и имеет синтаксис, который мне подходит (хотя я действительно ненавижу, что все методы регистров являются методами расширения).

некоторые другие рамки:

Ну, после просмотра вокруг лучшее сравнение, которое я нашел до сих пор:

Это был опрос, проведенный в марте 2010 года.

меня интересует то, что люди, которые использовали структуру DI/IoC и понравилось / не понравилось, StructureMap, кажется, выходит на первое место.

также из опроса, кажется, что замок.Виндзор и StructureMap кажется, наиболее благоприятным.

интересно, что единство и Spring.Net кажется, это популярные варианты, которые обычно не нравятся. (Я рассматривал Unity из лени (и значок Microsoft / поддержка), но я буду более внимательно смотреть на замок Виндзор и Теперь-структурная карта.)

конечно, наверное, это (?) не относится к Unity 2.0, который был выпущен в мае 2010 года.

надеюсь, кто-то еще может обеспечить сравнение, основанное на прямом опыте.

для сравнения net-ioc-фреймворки на Google code включая линфу и spring.net это не в вашем списке, пока я пишу этот текст.

Я работал с spring.net: он имеет много функций (aop, библиотеки, docu, ...) и есть большой опыт работы с ним в dotnet и java-мире. Функции являются модульными, поэтому вам не нужно принимать все функции. Эти функции являются абстракциями общих проблем, таких как databaseabstraction, loggingabstraction. однако это трудно сделать и отладить IOC-конфигурацию.

из того, что я читал до сих пор: если бы мне пришлось выбирать для небольшого или среднего проекта, я бы использовал ninject, так как IOC-конфигурация выполнена и отлаживается в c#. Но я еще не работал с ним. для большой модульной системы я бы остался spring.net из-за абстракции-библиотеки.