2017-10-20 2 views
0

프로젝트에서 나는 도메인 구동 디자인을 실행하고 ninject를 IOC 컨테이너로 사용하고 있습니다. Tony Truong here에 의해 설명 된 접근 방식과 비슷한 도메인 이벤트를 구현하려고합니다. 나는 정적 인 서비스를 갖거나 컴퍼 지션 루트 밖에서 커널을 참조 할 필요없이 ninject를 사용하려고 노력하고있다. 나는 목표는 발송 방법에 전달 도메인 이벤트 인스턴스의 유형에 등록 된 모든 핸들러를 호출하는 것입니다이Ninject를 사용하는 일반 인터페이스 다중 주입

/// <summary> 
/// Service to dispatch domain events to handlers. 
/// </summary> 
public class NinjectDomainEventDispatcher : IDomainEventDispatcher 
{ 
    /// <summary> 
    /// Array containing domain event handler registrations. 
    /// </summary> 
    private readonly IDomainEventHandler<IDomainEvent>[] _handlers; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="NinjectDomainEventDispatcher"/> class. 
    /// </summary> 
    /// <param name="handlers">Registered domain event handlers.</param> 
    public NinjectDomainEventDispatcher(IDomainEventHandler<IDomainEvent>[] handlers) 
    { 
     _handlers = handlers; 
    } 

    /// <summary> 
    /// Dispatch domain event to subscribed handlers. 
    /// </summary> 
    /// <typeparam name="T">Type of domain event to dispatch.</typeparam> 
    /// <param name="domainEvent">Domain event to dispatch.</param> 
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent 
    { 
     foreach (var handler in _handlers.Where(x => x.GetType() == typeof(IDomainEventHandler<T>))) 
     { 
      handler.Handle(domainEvent); 
     } 
    } 
} 

/// <summary> 
/// Module that will be used for the registration of the domain event handlers 
/// </summary> 
public class DomainEventHandlerModule : NinjectModule 
{ 
    /// <summary> 
    /// The method that will be used to load the ninject registration information. 
    /// </summary> 
    public override void Load() 
    { 
     Bind<IDomainEventDispatcher>().To<NinjectDomainEventDispatcher>(); 
     Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler1>(); 
     Bind<IDomainEventHandler<ConcreteDomainEvent>>().To<ConcreteDomainEventHandler2>(); 
     Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler1>(); 
     Bind<IDomainEventHandler<AnotherConcreteDomainEvent>>().To<AnotherConcreteDomainEventHandler2>(); 
    } 
} 

같은 것을 할 노력하고있어. 내 문제는, 처리기 배열이 비어 있습니다. IDomainEventHandler에 바인딩 된 핸들러를 특별히 찾고 있기 때문에 추측하겠습니다. <IDomainEvent> IDomainEvent를 구현하는 모든 처리기가 필요하지 않습니다. 대신에 자신의 코드에서 올바른 처리기에 대한 필터링의

+0

이 최근 답변을 사용하면 질문과 매우 유사 해 보일 수 있습니다. htt38 : //stackoverflow.com/a/46729694/1236044 – jbl

+0

나는 정적 이벤트 디스패처 및 내 도메인 오히려 이벤트를 반환합니다. 응용 프로그램/통합 계층은 다른 BC도이 BC의 이벤트에만 관심을 가질 수 있고 동일한 BC의 다른 집계 만 관심을 가질 가능성이 있기 때문에 이벤트를 게시/발생시킵니다. 게시를 수행하는 데 필요한 메커니즘이 필요하지만 컨트롤러/응용 프로그램 계층에 삽입되어 거기에서 사용됩니다. 그냥 그래 :) –

답변

0

, 당신은 당신을 위해 그렇게 할 Ninject에 사용할 수 있습니다

public class NinjectDomainEventDispatcher : IDomainEventDispatcher 
{ 
    private readonly IResolutionRoot resolutionRoot; 

    public NinjectDomainEventDispatcher(IResolutionRoot resolutionRoot) 
    { 
     this.resolutionRoot = resolutionRoot; 
    } 

    public void Dispatch<T>(T domainEvent) where T : IDomainEvent 
    { 
     var handlers = this.resolutionRoot.GetAll<IDomainEventHandler<T>>(); 
     foreach (var handler in handlers) 
     { 
      handler.Handle(domainEvent); 
     } 
    } 
} 

프로 팁 : 권장 디자인 연습 (IResolutionRoot에 따라 코드를 이동해서 Ninject입니다)을 composition root의 공장 구현으로 변경합니다. 수동으로 수행하는 대신 Ninject.Extensions.Factory

관련 문제