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