如何使用嵌套开放泛型的复合处理程序?

时间:2014-05-22 15:09:40

标签: c# dependency-injection simple-injector open-generics

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()))));

如果我打电话给&#34; _container.GetInstance(handlerType)&#34;而不是&#34; GetAllInstances&#34;发生错误:

  

开放通用类型的注册出错   IMessageHandler。无法为类型构建注册   ValidateMessageEnvelopeHandler取代。   开放泛型类型的注册出错   IMessageHandler。无法为类型构建注册   SecureMessageEnvelopeHandler。的构造函数   SecureMessageEnvelopeHandler类型包含   带有名称的IMessageHandler类型的参数   &#39; innerHandler&#39;那是没有注册的。请确保   IMessageHandler在容器中注册,或   改变的构造函数   SecureMessageEnvelopeHandler。

当我注册CompositeHandler()时,我有错误。 (Container.RegisterOpenGeneric(typeof(IMessageHandler&lt;&gt;),typeof(CompositeMessageHandler&lt;&gt;));)

  

开放通用类型的注册出错   IMessageHandler。无法为类型构建注册   ValidateMessageEnvelopeHandler取代。   ResolveUnregisteredType事件的多个观察者是   注册相同服务类型的委托:   IMessageHandler取代。确保   只有一个注册处理程序调用   ResolveUnregisteredType.Register方法,用于给定的服务类型。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您的配置无效,因为您做错了两件事:

  1. 您没有注册CompositeMessageHandler<T>
  2. 您正在呼叫GetAllInstances而不是GetInstance
  3. 当您致电GetAllInstances时,您只会获得使用RegisterManyForOpenGeneric注册的处理程序集合,但在您的示例中,您正在请求IMessageHandler<ValidateMessageEnvelope<SecureMessageEnvelope<ItemCreatedEvent>>>,但您从未注册过IMessageHandler<ValidateMessageEnvelope<T>> 1}}作为集合; ValidateMessageEnvelopeHandler已注册为&#39;单项&#39;注册

    CompositeMessageHandler<T>的注册有点进化,因为您不希望为所有IMessageHandler<T>注册返回合并。你不想要这个,因为如果消息是ValidateMessageEnvelope<T>,你想要返回ValidateMessageEnvelopeHandler<T>,如果消息是SecureMessageEnvelope<T>,你想要返回{{ 1}}。

    因此,您需要在SecureMessageEnvelopeHandler<T>ValidateMessageEnvelope<T>的注册后添加以下注册:

    SecureMessageEnvelopeHandler<T>

    通过提供container.RegisterOpenGeneric( typeof(IMessageHandler<>), typeof(CompositeMessageHandler<>), Lifestyle.Singleton, context => !context.Handled); ,您确保仅在未首先应用其他注册的情况下才会应用context => !context.Handled。如果没有这个谓词,Simple Injector将检测到两个开放式通用注册应用于同一个抽象,而Simple Injector将抛出异常。

    您应该只是致电CompositeMessageHandler<T>,而不是致电GetAllInstances。例如:

    GetInstance

    请注意,您的var ev = new ItemCreatedEvent().AsSecure("token/1").AsValidatable(); var handlerType = typeof(IMessageHandler<>).MakeGenericType(ev.GetType()); dynamic handler = container.GetInstance(handlerType); handler.Handle((dynamic)ev); 不仅会应用于MessageLogDecorator<T>LogService课程,还会应用于ProjectionService课程。这可能不是你想要的。您可能希望 - 仅包装CompositeMessageHandler<T>,或者您可能希望包装除CompositeMessageHandler<T>之外的所有内容。在最后一种情况下,您可以将CompositeMessageHandler<T>的注册更改为以下内容:

    MessageLogDecorator<T>

    或者您甚至可以将其简化为以下内容:

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

    在这种情况下,装饰器将只包含在非通用实现中。