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方法,用于给定的服务类型。
我该如何解决这个问题?
答案 0 :(得分:1)
您的配置无效,因为您做错了两件事:
CompositeMessageHandler<T>
GetAllInstances
而不是GetInstance
。当您致电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<>));
});
在这种情况下,装饰器将只包含在非通用实现中。