주요 C # DI / IoC 프레임 워크는 어떻게 비교됩니까? [닫은]


308

성전으로 진출 할 위험에 처해있는이 인기있는 DI / IoC 프레임 워크의 강점과 약점은 무엇이며 쉽게 최고로 간주 될 수 있습니까? .. :

  • 닌 젝트
  • 통일
  • Castle.Windsor
  • 오토 팩
  • 구조도

여기에 나열되지 않은 다른 C # 용 DI / IoC 프레임 워크가 있습니까?

유스 케이스와 관련하여 클라이언트 WPF 앱과 WCF / SQL 서비스 인프라, 사용 편의성 (특히 명확하고 간결한 구문 측면에서), 일관된 문서, 우수한 커뮤니티 지원 및 성능이 모두 중요한 요소입니다. 내 선택에.

최신 정보:

인용 된 자료와 중복 된 질문이 오래된 것 같습니다. 이러한 모든 프레임 워크에 대한 지식을 가진 사람이 앞으로 나와 실제 통찰력을 제공 할 수 있습니까?

나는이 주제에 대한 대부분의 의견이 편향 될 가능성이 있다는 것을 알고 있지만, 누군가가이 모든 프레임 워크를 연구하는 데 시간이 걸리고 적어도 일반적으로 객관적인 비교를하기를 희망합니다.

이전에이 작업을 수행하지 않은 경우 자체 조사를 수행 할 의향이 있지만 적어도 몇 사람이 이미 수행 한 것으로 가정했습니다.

두 번째 업데이트 :

하나 이상의 DI / IoC 컨테이너에 대한 경험이있는 경우 해당 장단점을 평가하고 요약하십시오. 감사합니다. 이것은 사람들이 만든 모호한 작은 컨테이너를 모두 발견하는 연습이 아니며, 인기 있고 활동적인 프레임 워크 간의 비교를 찾고 있습니다.


1
[Ninject vs Unity for DI]와 같은 질문 이지만 ( stackoverflow.com/questions/1054801/ninject-vs-unity-for-di ) 후속 조치가 필요할 수 있습니다.
Matthew Flaschen

2
[비교 성 윈저 화합 StructureMap (가능 중복 stackoverflow.com/questions/2216684/... )
마우 페르

@slomojo : 가능한 중복. stackoverflow.com/questions/4509458/ioc-comparisions-closed . 또한 답변에서 IoC의 인기를 보여주는 링크가 있습니다. 한번보세요
dhinesh

@chibacity-나는 그것을 사용했다. 우리는 Unity를 둘 다 제거하고 StructureMap으로 교체했으며 생성자 주입은 간단하고 구성은 깨끗하고 유지 관리가 가능했습니다. 개인적으로 AutoFac을 가지고 놀았지만, 그것을 이해하기 위해 약간의 문서가 필요했습니다. 나머지는 내가 읽은 것에 대해서만 언급 할 수 있습니다.
Phill

우리가 SSRS와 관련하여 한 가지 문제는 조용히 실패하고 실패한 이유를 알 수 없었던 코드를 단계별로 실행했지만 예외는 모호했습니다. 일주일 동안 해결 방법을 작성하여 작업했습니다. 결국 우리가 StructureMap으로 옮길 때 또 다른 시도가 있었고 'ObjectFactory.WhatDoIHave ()'를 사용하여 몇 분 안에 어셈블리가 AppDomain에로드되기 전에 IoC가 구성되고 있음을 알게되어 인터페이스가 콘크리트에 등록되지 않았습니다. 유형.
Phill

답변:


225

이 질문에 대한 종합적인 답변은 제 책 의 수백 페이지를 차지하지만, 여전히 작업중인 빠른 비교 차트는 다음과 같습니다.

여러 DIC의 차이점을 설명하는 표


40
나는 당신의 책의 MEAP을 읽었으며 왜 당신이 그것을 Ninject에서 빠져 나왔는지 궁금합니다.
Martin Owen

2
부분 답변은 여기에서 찾을 수 있습니다 : manning-sandbox.com/thread.jspa?threadID=38943
Mark Seemann

25
@Mark, 이것에 감사합니다. 귀하의 답변에 Ninject가 포함될 수 있기를 바랍니다 (중요한 것은 광고를 둘러싼 새로운 광고뿐만 아니라 새로운 언어 기능의 사용 때문이기도합니다)
ocodo

3
Ninject는 AutoFac과 유사하지만 여러 가지 방법으로 NUGET 팀에서 사용하며 가장 많이 다운로드 된 IOC 컨테이너가 제공됩니다. 나는 그것이 .NET 책의 Mark 's Dependency Injection에 있지 않은 것에 실망했습니다. 업계가 보이는 방식에 2 판이 있다면, 그것이 책에 들어가게되기를 바랍니다. 나는 Unity, MEF (실제 DI가 아님), Ninject 또는 StructurMap을 사용하지만 spring.net 또는 autofac 등을 사용하는 계약 또는 원격 공연에 아직 착륙하지 못했습니다 ...
Tom Stickel

2
유니티 3.5는 이미 규칙 기반의 등록을 지원합니다 nuget.org/packages/Unity/3.5.1404 . 한 가지 단점을 제거 ;-)
Vladimir Dorokhov

116

다른 성능 비교 (2014 년 4 월 10 일 최신 업데이트)를 발견했습니다. 다음을 비교합니다.

다음은 게시물의 간략한 요약입니다.

결론

Ninject는 확실히 가장 느린 컨테이너입니다.

MEF, LinFu 및 Spring.NET은 Ninject보다 빠르지 만 여전히 느립니다. AutoFac, Catel 및 Windsor가 이어지고 StructureMap, Unity 및 LightCore가 이어집니다. Spring.NET의 단점은 XML로만 구성 할 수 있다는 것입니다.

SimpleInjector, Hiro, Funq, Munq 및 Dynamo는 최고의 성능을 제공하며 매우 빠릅니다. 그들에게 시도하십시오!

특히 Simple Injector가 좋은 선택 인 것 같습니다. 매우 빠르며 문서가 훌륭하며 차단 및 일반 데코레이터와 같은 고급 시나리오도 지원합니다.

Common Service Selector Library를 사용 해보고 여러 옵션을 시도해보고 자신에게 가장 적합한 것을 볼 수도 있습니다.

사이트에서 Common Service Selector 라이브러리에 대한 일부 정보 :

라이브러리는 IoC 컨테이너 및 서비스 로케이터에 대한 추상화를 제공합니다. 라이브러리를 사용하면 애플리케이션이 하드 참조에 의존하지 않고 기능에 간접적으로 액세스 할 수 있습니다. 이 라이브러리를 사용하면 타사 응용 프로그램과 프레임 워크가 특정 구현에 연결되지 않고 IoC / 서비스 위치를 활용할 수 있습니다.

최신 정보

2011 년 9 월 13 일 : FunqMunq 가 참가자 목록에 추가되었습니다. 차트도 업데이트되었으며 성능이 저하되어 Spring.NET이 제거되었습니다.

04.11.2011 : " Simple Injector 추가 , 성능은 모든 참가자 중 최고입니다".


(비교 링크를 따름) 최근에 업데이트되어 속도 차이 (및 기본 기능 매트릭스)를 볼 수 있습니다. 감사.
lko

내가 아는 한 Ninject는 Interception과 XML 구성 모두에 대한 확장 기능을 가지고 있지만 비교는 그렇지 않기 때문에 그 비교는 신뢰할 수 없습니다.
다니엘

15
이것은 매우 정량적 인 비교입니다. 파일 크기 또는 필요한 종속성 수와 같은 비 성능 기능은 어떻습니까? 또한 문서 품질이나 유용성과 같은 주관적인 조치가 도움이 될 것입니다. 내 요점은 속도 이외의 요소를 고려해야한다는 것입니다.
FistOfFury

1
Jeremy Miller와 마찬가지로 StructureMap의 저자는 과거에 다음과 같이 말한 바 있습니다.
Tom Stickel


49

그냥이 위대한 읽어 닷넷 DI 컨테이너 비교 블로그 필립 매트로합니다.

그는 철저한 성능 비교 테스트를 수행합니다.

그는 작고 빠르며 사용하기 쉬운 Autofac 을 권장 합니다 ... 동의합니다. 그의 테스트에서 UnityNinject 가 가장 느린 것으로 보입니다 .


5
.Net DI 컨테이너 속도 Redux 게시물에 대한 업데이트가 있습니다 . 결론적으로, Unity에 대한 잘못된 접근 방식이 처음에 이루어졌습니다. 새로운 측정으로 Unity가 훨씬 좋아 보입니다.
Volker von Einem

33

면책 조항 : 2015 년 초 현재 Jimmy Bogard 의 IoC 컨테이너 기능 을 크게 비교 한 내용은 다음과 같습니다.

비교 된 컨테이너 :

  • 오토 팩
  • 닌 젝트
  • 간단한 인젝터
  • 구조도
  • 통일
  • 윈저

시나리오는 다음과 같습니다. 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)

일반 분산 설정 (기본 INotification / 생성 요청 파이프 라인에 대한 처리기 등록) 처리기는 매우 간단하며 콘솔에 출력됩니다.

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 */ }

오토 팩

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();
  • 오픈 제네릭 : 예, 암시 적으로
  • 여러 개의 열린 제네릭 : 예, 암시 적으로
  • 일반적인 모순 : 예, 명시 적

닌 젝트

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 사용)

구조도

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;
}
  • 오픈 제네릭 : 예, 암시 적으로
  • 다중 공개 제네릭 : 예, 사용자 빌드 확장 기능
  • 일반적인 모순 : derp

윈저

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • 오픈 제네릭 : 예, 암시 적으로
  • 여러 개의 열린 제네릭 : 예, 암시 적으로
  • 일반적인 반 공예 : 예, 사용자 작성 확장

우수한! 위의 요약에서 Btw는 Windsor를 놓쳤지만 Jimmy의 원본 기사에서 볼 수 있습니다.
Louis

와우 아무도 그것에 대해 전에 경고하지 않았다 (: 나는 윈저를 추가했다 @Louis
stratovarius

21

실제로 수많은 IoC 프레임 워크가 있습니다. 모든 프로그래머가 경력의 어느 시점에서 하나를 쓰려고하는 것 같습니다. 아마도 그것을 출판하지 말고 내면의 일을 배우십시오.

autofac은 매우 유연하고 나에게 맞는 구문을 가지고 있기 때문에 개인적으로 선호합니다 (모든 레지스터 메소드가 확장 메소드라는 것을 정말로 싫어하지만).

다른 프레임 워크 :


안녕하세요 @abatishchev! :) ... 원래의 아이디어는 타사 및 기본 제공 방법이 동일한 기반에 있는지 확인하는 것이 었습니다. 많은 "register"메소드는 별도로 배송해야합니다 (예 : RegisterControllers()MVC). 그런 경우를 중심으로 디자인하는 것이 가치가 있다고 생각했습니다. (5 년 이상 전에 디자인되었습니다.)
Nicholas Blumhardt

1
@NicholasBlumhardt : 안녕! :) 늦게 답변해서 죄송합니다. 다른 사람들과의 알림이 유실되었습니다. 실제로 그러한 일관성을 위해 나에게 의미가 있습니다. 지금 어떻게 생각하십니까? 어떻게 설계 하시겠습니까?
abatishchev

@abatishchev 나는 jgauffin에 동의하지 않습니다. 확장 방법은 확장을 위해 닫히지 않으며 확장입니다. 프레임 워크의 핵심은 모든 기능을 수행 할 수 있고 확장 메소드를 사용하면 추가 기능 (일부 기본 도우미)을 제공 할 수 있지만 다른 사람은 누구나 자유롭게 자신의 확장을 작성할 수 있습니다. 나는 당신의 프레임 워크가 확장 메소드를 확장 확장 메소드를 받아들이 면 좋은 프레임 워크라고 말할 것이다 .
t3chb0t

6

글쎄, 지금까지 내가 찾은 최고의 비교를 살펴본 결과는 다음과 같습니다.

2010 년 3 월에 실시 된 여론 조사입니다.

DI / IoC 프레임 워크를 사용하고 마음에 들거나 싫어하는 사람들이 StructureMap을 사용하는 것으로 나타났습니다.

또한 여론 조사에서 Castle.WindsorStructureMap 이 가장 선호되는 것 같습니다.

흥미롭게도 UnitySpring.Net 은 가장 일반적으로 싫어하는 인기있는 옵션 인 것 같습니다. (나는 게으름에서 Unity를 고려하고 있었고 Microsoft 배지 / 지원), 지금 Castle Windsor와 StructureMap을 더 자세히 살펴볼 것입니다.

물론 이것은 아마도 (?) 2010 년 5 월에 릴리스 된 Unity 2.0에는 적용되지 않습니다.

다른 누군가가 직접적인 경험을 바탕으로 비교를 할 수 있기를 바랍니다.


2
화합은 꽤 좋습니다. 순환 의존성을 해결하지 못한다고 불평하는 사람들도 있지만 대부분 필요한 것을 다룹니다. 나는 그것을 좋아한다. 나는 필요한 모든 것을한다.
Dmitri Nesteruk

많은 개발자들이 몰라도 Castle.Windsor 를 사용 하고 있습니다. NHibernate 의 기본 Ioc입니다 . (적어도 FluentNHibernate i가 어제 내려졌다). 또한 LinFu nstead를 사용하는 NHibernate 구현을 보았습니다
k3b

5

이 텍스트를 작성하는 동안 목록에없는 linfu 및 spring.net을 포함한 Google 코드net-ioc-frameworks 비교를 참조하십시오 .

나는 spring.net으로 일했다 : 그것은 많은 기능 (aop, 라이브러리, docu 등)을 가지고 있으며 닷넷과 자바 세계에서 많은 경험이있다. 기능은 모듈화되어 있으므로 모든 기능을 사용할 필요는 없습니다. 이 기능은 데이터베이스 요약, 로깅 요약과 같은 일반적인 문제의 추상화입니다. 그러나 IoC 구성을 수행하고 디버깅하기가 어렵습니다.

내가 지금까지 읽은 것에서 : 중소 프로젝트를 선택해야한다면 ioc 구성이 완료되고 c #에서 디버깅 할 수 있기 때문에 ninject를 사용합니다. 그러나 나는 아직 그것을 사용하지 않았습니다. 대형 모듈 시스템의 경우 추상화 라이브러리 때문에 spring.net을 유지합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.