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

如果我调用“_container.GetInstance(handlerType)”而不是“GetAllInstances”,则会发生错误:

注册开放泛型类型 IMessageHandler 时出错。无法为类型 ValidateMessageEnvelopeHandler> 构建注册。注册开放泛型类型 IMessageHandler 时出错。无法为 SecureMessageEnvelopeHandler 类型构建注册。SecureMessageEnvelopeHandler 类型的构造函数包含名称为“innerHandler”的 IMessageHandler 类型的参数,该参数未注册。请确保在容器中注册了 IMessageHandler,或者更改 SecureMessageEnvelopeHandler 的构造函数。

当我注册 CompositeHandler () 我有错误。( Container.RegisterOpenGeneric(typeof(IMessageHandler<>), typeof(CompositeMessageHandler<>));)

注册开放泛型类型 IMessageHandler 时出错。无法为类型 ValidateMessageEnvelopeHandler> 构建注册。ResolveUnregisteredType 事件的多个观察者正在为同一服务类型注册一个委托:IMessageHandler>。确保只有一个已注册的处理程序调用给定服务类型的 ResolveUnregisteredType.Register 方法。

我怎样才能解决这个问题?

4

1 回答 1

1

您的配置不起作用,因为您做错了两件事:

  1. 你没有注册CompositeMessageHandler<T>
  2. 你打电话GetAllInstances而不是GetInstance.

当您调用时,GetAllInstances您只会获得使用 注册的处理程序集合RegisterManyForOpenGeneric,但在您的示例中,您请求的是IMessageHandler<ValidateMessageEnvelope<SecureMessageEnvelope<ItemCreatedEvent>>>,但您从未将 an 注册IMessageHandler<ValidateMessageEnvelope<T>>为集合;被ValidateMessageEnvelopeHandler注册为“单项”注册。

的注册CompositeMessageHandler<T>更加先进,因为您不希望为所有IMessageHandler<T>注册返回复合材料。你不想要这个,因为如果消息是 a ValidateMessageEnvelope<T>,你想返回 the ValidateMessageEnvelopeHandler<T>,如果消息是 a SecureMessageEnvelope<T>,你想返回SecureMessageEnvelopeHandler<T>

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

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

通过提供context => !context.Handled,您可以确保CompositeMessageHandler<T>只有在没有首先应用其他注册的情况下才会应用。如果没有这个谓词,Simple Injector 将检测到两个开放通用注册应用于同一个抽象,Simple Injector 将抛出异常。

而不是打电话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>不仅会应用于LogServiceProjectionService类,还会应用于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<>));
    });

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

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

在这种情况下,装饰器只会被非泛型实现包裹。

于 2014-05-22T16:09:59.930 回答