2014-05-22 8 views
1
public interface IMessage { } 
public interface ICommand : IMessage { } 
public interface IEvent : IMessage { } 

public interface IMessageHandler<T> { 
    void Handle(T message); 
} 

public class ItemCreatedEvent : IEvent { 
    public string Name { get; set; } 
} 

public class ValidateMessageEnvelope<TMessage> { 
    public TMessage Message { get; set; } 
    public ValidateMessageEnvelope(TMessage message){ 
     Message = message; 
    } 
} 

public class ValidateMessageEnvelopeHandler<TMessage> 
    : IMessageHandler<ValidateMessageEnvelope<TMessage>> { 
    private readonly IMessageHandler<TMessage> _innerHandler; 
    public ValidateMessageEnvelopeHandler(IMessageHandler<TMessage> innerHandler){ 
     _innerHandler = innerHandler; 
    } 
    public void Handle(ValidateMessageEnvelope<TMessage> message){ 
     _innerHandler.Handle(message.Message); 
    } 
} 

public class SecureMessageEnvelope<TMessage> { 
    public TMessage Message { get; set; } 
    public string UserToken { get; set; } 
    public SecureMessageEnvelope(TMessage message, string userToken){ 
     Message = message; 
     UserToken = userToken; 
    } 
} 

public class SecureMessageEnvelopeHandler<TMessage> 
    : IMessageHandler<SecureMessageEnvelope<TMessage>> 
{ 
    private readonly IMessageHandler<TMessage> _innerHandler; 
    public SecureMessageEnvelopeHandler(IMessageHandler<TMessage> innerHandler){ 
     _innerHandler = innerHandler; 
    } 
    public void Handle(SecureMessageEnvelope<TMessage> message){ 
     _innerHandler.Handle(message.Message); 
    } 
} 

public class MessageLogDecorator<TMessage> : IMessageHandler<TMessage> 
    where TMessage : IEvent { 
    private readonly IMessageHandler<TMessage> _messageHandler; 
    public MessageLogDecorator(IMessageHandler<TMessage> messageHandler) { 
     _messageHandler = messageHandler; 
    } 
    public void Handle(TMessage message){ 
     Console.WriteLine("Event Log: {0}",JsonConvert.SerializeObject(message)); 
     _messageHandler.Handle(message); 
    } 
} 

public class CompositeMessageHandler<TMessage> : IMessageHandler<TMessage> { 
    private readonly IEnumerable<IMessageHandler<TMessage>> _handlers; 
    public CompositeMessageHandler(IEnumerable<IMessageHandler<TMessage>> handlers){ 
     _handlers = handlers; 
    } 
    public void Handle(TMessage message) { 
     foreach (var messageHandler in _handlers) { 
      messageHandler.Handle(message); 
     } 
    } 
} 

public class LogService :IMessageHandler<ItemCreatedEvent> { 
    public void Handle(ItemCreatedEvent message) {} 
} 

public class ProjectionService: IMessageHandler<ItemCreatedEvent> { 
    public void Handle(ItemCreatedEvent message) { } 
} 

public static class Extensions{ 
    public static SecureMessageEnvelope<TMessage> AsSecure<TMessage>(
     this TMessage message, string userToken){ 
     return new SecureMessageEnvelope<TMessage>(message, userToken); 
    } 
    public static ValidateMessageEnvelope<TMessage> AsValidatable<TMessage>(
     this TMessage message){ 
     return new ValidateMessageEnvelope<TMessage>(message); 
    } 
} 

등록 :중첩 된 열린 일반 함께 복합 처리기를 사용하는 방법?

Container.RegisterManyForOpenGeneric(typeof (IMessageHandler<>), 
    Container.RegisterAll, 
    Assembly.GetExecutingAssembly()); 

// handle all ValidateMessageEnvelope<TMessage> messages 
Container.RegisterOpenGeneric(typeof(IMessageHandler<>), 
    typeof(ValidateMessageEnvelopeHandler<>)); 

// handle all SecureMessageEnvelope<TMessage> messages 
Container.RegisterOpenGeneric(typeof(IMessageHandler<>), 
    typeof(SecureMessageEnvelopeHandler<>)); 

// handle all IEvent messages 
Container.RegisterDecorator(typeof(IMessageHandler<>), 
    typeof(MessageLogDecorator<>)); 

이벤트 전화

var ev = new ItemCreatedEvent().AsSecure("token/1").AsValidatable(); 
    var handlerType = typeof(IMessageHandler<>).MakeGenericType(ev.GetType()); 
    foreach (dynamic handler in _container.GetAllInstances(handlerType)){ 
     handler.Handle((dynamic)ev);  
    } 

빈 반환하지만,이 핸들러 반환해야합니다 : 다음과 같이 좋을 텐데 있지만

handler[0] = 
    new ValidateMessageEnvelopeHandler<SecureMessageEnvelope<ItemCreatedEvent>>(
     new SecureMessageEnvelopeHandler<ItemCreatedEvent>(
      new MessageLogDecorator<ItemCreatedEvent>(
       new LogService()))); 

handler[1] = 
    new ValidateMessageEnvelopeHandler<SecureMessageEnvelope<ItemCreatedEvent>>(
     new SecureMessageEnvelopeHandler<ItemCreatedEvent>(
      new MessageLogDecorator<ItemCreatedEvent>(
       new ProjectionService()))); 

을 :

new ValidateMessageEnvelopeHandler<SecureMessageEnvelope<ItemCreatedEvent>>(
    new SecureMessageEnvelopeHandler<ItemCreatedEvent>(
     new CompositeHandler(
      new MessageLogDecorator<ItemCreatedEvent>(
       new LogService()), 
      new MessageLogDecorator<ItemCreatedEvent>(
       new ProjectionService())))); 

나는 오류가 발생 대신 "GetAllInstances"의 "_container.GetInstance (handlerType)"호출하는 경우 :

개방형 제네릭 형식 IMessageHandler의 등록에 오류가 발생했습니다. 유형 ValidateMessageEnvelopeHandler>에 대한 등록을 작성하지 못했습니다. 개방형 제네릭 유형 IMessageHandler 등록에 오류가있었습니다. 유형 SecureMessageEnvelopeHandler에 대한 등록을 작성하는 데 실패했습니다. SecureMessageEnvelopeHandler 형식의 생성자에 'innerHandler'라는 이름의 IMessageHandler 형식의 매개 변수가 포함되어 있습니다.이 매개 변수는 등록되지 않았습니다. IMessageHandler가 컨테이너에 등록되어 있거나 의 생성자가 SecureMessageEnvelopeHandler로 변경되어 있는지 확인하십시오.

CompositeHandler()를 등록 할 때 오류가 있습니다. (Container.RegisterOpenGeneric (대해서 typeof (IMessageHandler <>)의 typeof (CompositeMessageHandler <>)))

오픈 범용 형 IMessageHandler 등록의 오류가 있었다. 유형 ValidateMessageEnvelopeHandler>에 대한 등록을 작성하지 못했습니다. ResolveUnregisteredType 이벤트의 여러 관찰자는 동일한 서비스 유형 ( IMessageHandler>)에 대한 대리자를 에 등록합니다. 등록 된 처리기 중 하나만 ResolveUnregisteredType.Register 메서드를 특정 서비스 유형에 대해 호출해야합니다.

어떻게 해결할 수 있습니까? 당신 잘못이 일을하고 있기 때문에

답변

1

귀하의 구성은 작동하지 않습니다

  1. 당신은 당신은 GetAllInstances 대신 GetInstance 호출하는 CompositeMessageHandler<T>
  2. 를 등록하지 않았습니다.

당신 만 RegisterManyForOpenGeneric를 사용하여 등록 된 처리기의 컬렉션을 얻을 수 있지만 예를 들어 당신이 IMessageHandler<ValidateMessageEnvelope<SecureMessageEnvelope<ItemCreatedEvent>>>를 요청 GetAllInstances 전화,하지만 당신은 콜렉션으로서 IMessageHandler<ValidateMessageEnvelope<T>>을 등록하지; ValidateMessageEnvelopeHandler은 '단일 품목'등록으로 등록됩니다.

모든 IMessageHandler<T> 등록에 대해 컴포지트가 반환되기를 원하지 않으므로 CompositeMessageHandler<T>에 대한 등록이 조금 더 진화되었습니다. 메시지가 ValidateMessageEnvelope<T> 인 경우 ValidateMessageEnvelopeHandler<T>을 반환하고 메시지가 SecureMessageEnvelope<T> 인 경우 SecureMessageEnvelopeHandler<T>을 반환하려는 경우이 작업을 원하지 않습니다.

그래서 당신은 ValidateMessageEnvelope<T>SecureMessageEnvelopeHandler<T>에 대한 등록 후에 다음 등록을 추가해야합니다

container.RegisterOpenGeneric(
    typeof(IMessageHandler<>), 
    typeof(CompositeMessageHandler<>), 
    Lifestyle.Singleton, 
    context => !context.Handled); 

context => !context.Handled을 공급함으로써, 당신은 다른 등록이 먼저 적용되지 않은 경우 CompositeMessageHandler<T>에만 적용됩니다 있는지 확인하십시오. 이 술어가 없으면 Simple Injector는 두 개의 공개 제네릭 등록이 동일한 추상화에 적용되고 Simple Injector가 예외를 throw한다는 것을 감지합니다.

GetAllInstances을 호출하는 대신 GetInstance을 호출하면됩니다. 예를 들어 : 당신의 MessageLogDecorator<T>CompositeMessageHandler<T> 클래스도 LogServiceProjectionService 클래스에 적용하지만, 얻을하지 않습니다하지만

var ev = new ItemCreatedEvent().AsSecure("token/1").AsValidatable(); 
var handlerType = typeof(IMessageHandler<>).MakeGenericType(ev.GetType()); 

dynamic handler = container.GetInstance(handlerType); 

handler.Handle((dynamic)ev); 

주의 마십시오. 이것은 당신이 원하는 것이 아닐 수도 있습니다. CompositeMessageHandler<T>을 -only-wrap하거나 CompositeMessageHandler<T>을 제외한 모든 것을 랩핑하고 싶을 수도 있습니다.

container.RegisterDecorator(typeof(IMessageHandler<>), 
    typeof(MessageLogDecorator<>), context => 
    { 
     var type = context.ImplementationType; 
     return !type.IsGenericType || 
      type.GetGenericTypeDefinition() != typeof(CompositeMessageHandler<>)); 
    }); 

을 또는 당신도 다음에 간단하게 할 수 있습니다 : 마지막 경우 다음에 MessageLogDecorator<T>의 등록을 변경할 수 있습니다

container.RegisterDecorator(typeof(IMessageHandler<>), 
    typeof(MessageLogDecorator<>), 
    context => !context.ImplementationType.IsGenericType); 

경우 데코레이터 것에서 비 제네릭 구현물에 대해서만 포괄됩니다.

+0

답장을 보내 주셔서 감사합니다. 작품 .BTW CompositeMessageHandler <>가 필요합니까? – oguzh4n

+0

@ oguzh4n : 복합 패턴은 응용 프로그램 코드가이 코드 뒤에 여러 구현이 있다는 사실을 알 수 없도록합니다. 엔벨로프 핸들러를 사용하는 디자인에서는 분명히 이것을 필요로한다. 엔벨로프 핸들러와 '메시지 집행자 중재자'는 이러한 경우가 언제인지 전혀 알지 못합니다 (그리고 그들은 알 필요가 없습니다). – Steven