Как сравниваются основные фреймворки C# DI/IoC? [закрытый]
рискуя попасть на территорию Священной войны, каковы сильные и слабые стороны этих популярных структур DI/IoC, и можно ли легко считать лучшим? ..:
- Ninject
- единство
- замок.Виндзор!--4-->
- Autofac
- StructureMap
есть ли другие рамки DI/IoC для C#, которые я не перечислил здесь?
в контексте моего варианта использования я создаю клиентский WPF приложение и инфраструктура служб WCF / SQL, простота использования (особенно с точки зрения четкого и краткого синтаксиса), согласованная документация, хорошая поддержка сообщества и производительность-все это важные факторы в моем выборе.
обновление:
ресурсы и повторяющиеся вопросы, приведенные, по-видимому, устарели, может ли кто-то со знанием всех этих рамок выйти вперед и дать некоторое реальное представление?
Я понимаю, что большинство мнений по этому вопросу, вероятно, будет предвзято, но я надеюсь, что кто-то нашел время, чтобы изучить все эти рамки и иметь хотя бы в целом объективное сравнение.
Я вполне готов провести собственное расследование, если это не было сделано раньше, но я предположил, что это было что-то, по крайней мере, несколько человек уже сделали.
Второй Обновления:
Если у вас есть опыт работы с более чем одним контейнером DI/IoC, пожалуйста, оцените и обобщите плюсы и минусы тех, спасибо. Этот это не упражнение в обнаружении всех неясных маленьких контейнеров, которые люди сделали, я ищу сравнения между популярными (и активными) фреймворками.
7 ответов
в то время как исчерпывающий ответ на этот вопрос занимает сотни страниц моей книги, вот диаграмма быстрого сравнения, над которой я все еще работаю:
я наткнулся на другое представление сравнение(последнее обновление 10 апреля 2014 года). Он сравнивает следующее:
- AutoFac
- LightCore (сайт немецкий)
- LinFu
- Ninject
- Petite
- Простой Инжектор (самый быстрый из всех конкурсанты)
- Spring.NET
- StructureMap
- единство
- Виндзор
- Хиро
вот краткое резюме из поста:
вывод
Ninject, безусловно, самый медленный контейнер.
MEF, LinFu и Spring.NET быстрее, чем Ninject, но все же хорошенький медленный. Затем идут AutoFac, Catel и Windsor, а затем StructureMap, Единство и Лайткор. Недостаток Spring.NET есть, что может быть только настроен с помощью XML.
SimpleInjector, Hiro, Funq, Munq и Dynamo предлагают лучшее производительность, они очень быстрые. Дайте им попробовать!
особенно простой инжектор кажется хорошим выбором. Это очень быстро, имеет хорошее документация, а также поддерживает расширенные сценарии, такие как перехват и общие декораторы.
вы также можете попробовать использовать Библиотека Селектора Общих Служб и, надеюсь, попробовать несколько вариантов и посмотреть, что работает лучше для вас.
некоторая информация о библиотеке селектора общих служб с сайта:
библиотека предоставляет абстракцию над контейнерами и сервисом IoC локаторы. Использование библиотеки позволяет приложению получить косвенный доступ возможности без полагаться на крепко ссылки на литературу. Надеюсь, что с помощью этой библиотеки могут начинаться сторонние приложения и фреймворки чтобы использовать местоположение IoC/Service, не привязывая себя к конкретная реализация.
обновление
13.09.2011: Funq и частое были добавлены в список участников. Были также обновлены диаграммы и Spring.NET был удален из-за его плохого состояния спектакль.
04.11.2011: "добавил Простой Инжектор, спектакль-лучший из всех конкурсантов".
просто прочитайте это здорово .Net DI сравнение контейнеров блог Филипп мат.
Он делает некоторые тщательные тесты сравнения производительности;
он рекомендует 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);
- открытые дженерики: да, неявно
- несколько открытых дженериков: да, имплицитно
- Generic contravariance: да, с пользовательскими расширениями
Простой Инжектор
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;
}
- открытые дженерики: да, неявно
- несколько открытых дженериков: да, с пользовательским расширением
- универсальный контравариантность: баттхерт
Виндзор
var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
- открытые дженерики: да, неявно
- несколько открытых дженериков: да, имплицитно
- Generic contravariance: да, с пользовательским расширением
на самом деле есть куча рамок МОК. Кажется, что каждый программист пытается написать его в какой-то момент своей карьеры. Может быть, не публиковать его, но узнать внутреннее устройство.
Я лично предпочитаю autofac, так как он довольно гибкий и имеет синтаксис, который мне подходит (хотя я действительно ненавижу, что все методы регистра являются методами расширения).
некоторые другие рамки:
Ну, посмотрев вокруг лучшее сравнение, которое я нашел до сих пор является:
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
Это был опрос, проведенный в марте 2010 года.
один момент интереса для меня заключается в том, что люди, которые использовали структуру DI/IoC и понравилось/не понравилось, StructureMap, похоже, выходит на первое место.
также из опроса, кажется, что замок.Виндзор!--6--> и StructureMap кажется, наиболее благосклонны.
интересно, что единство и Spring.Net кажутся популярными вариантами, которые в основном не нравятся. (Я рассматривал Единство из лени (и значок Microsoft / поддержка), но я буду более внимательно смотреть на замок Виндзор и Помощью StructureMap сейчас.)
конечно, наверное, это (?) не относится к Unity 2.0, который был выпущен в мае 2010 года.
надеюсь, кто-то еще может предоставить сравнение, основанное на прямом опыте.
для сравнения net-ioc-фреймворки в коде google включая линфу и spring.net этого нет в твоем списке, пока я пишу это сообщение.
Я работал с spring.net: он имеет множество функций (aop, библиотеки, docu,...) и есть большой опыт работы с ним в dotnet и java-мире. Функции модульные, поэтому вы не должны принимать все функции. Функции являются абстракциями общих проблем, таких как databaseabstraction, loggingabstraction. однако это сложно сделать и отладить МОК-конфигурации.
из того, что я прочитал до сих пор: если бы мне пришлось выбирать для малого или среднего проекта, я бы использовал ninject, так как IOC-конфигурация выполнена и отлаживается в c#. Но я еще не работал с ним. для большой модульной системы я бы остался с spring.net из-за абстракции-библиотеки.