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

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

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

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

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

최신 정보:

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

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

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

두 번째 업데이트 :

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



답변

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

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


답변

다른 성능 비교 (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 추가 , 성능은 모든 참가자 중 최고입니다”.


답변

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

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

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


답변

면책 조항 : 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());
  • 오픈 제네릭 : 예, 암시 적으로
  • 여러 개의 열린 제네릭 : 예, 암시 적으로
  • 일반적인 반 공예 : 예, 사용자 작성 확장

답변

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

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

다른 프레임 워크 :


답변

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

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

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

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

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

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

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


답변

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

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

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