首先我会为你的消息,只是一个基本的处理标记一个小的实现,为了测试
public class MessageA : IMessage
{
public bool Handled
{
get;
private set;
}
public void MarkAsHandled()
{
this.Handled = true;
}
}
public class MessageB : IMessage
{
public bool Handled
{
get;
private set;
}
public void MarkAsHandled()
{
this.Handled = true;
}
}
现在,让我们执行这两个处理程序为:
public class MessageAHandler : IMessageHandler<MessageA>
{
public void Handle(MessageA message)
{
message.MarkAsHandled();
}
}
public class MessageBHandler : IMessageHandler<MessageB>
{
public void Handle(MessageB message)
{
message.MarkAsHandled();
}
}
作为一个方面说明,您可能希望将IMessageHandler接口标记为公共(如果可见性设置为内部,则会出现编译器错误)。
现在让我们添加一个小的处理程序:
public interface IMessageHandler
{
Type MessageType { get; }
void Handle(IMessage message);
}
public class MessageHandlerAdapter<T> : IMessageHandler where T : IMessage
{
private readonly Func<IMessageHandler<T>> handlerFactory;
public MessageHandlerAdapter(Func<IMessageHandler<T>> handlerFactory)
{
this.handlerFactory = handlerFactory;
}
public void Handle(IMessage message)
{
var handler = handlerFactory();
handler.Handle((T)message);
}
public Type MessageType
{
get { return typeof(T); }
}
}
我们现在可以实现的messageReceiver这样:
public class MessageReceiver
{
private readonly IEnumerable<IMessageHandler> handlers;
public MessageReceiver(IEnumerable<IMessageHandler> handlers)
{
this.handlers = handlers;
}
public void ReceiveMessage(IMessage message)
{
var handler = this.handlers.Where(h => h.MessageType == message.GetType()).FirstOrDefault();
if (handler != null)
{
handler.Handle(message);
}
else
{
//Do something here, no handler found for message type
}
}
}
现在来测试我们的信息被正确处理,这里是一个小测试:
[TestClass]
public class TestSelector
{
private IContainer container;
[TestMethod]
public void TestMethod()
{
var processor = container.Resolve<MessageReceiver>();
MessageA ma = new MessageA();
MessageB mb = new MessageB();
processor.ReceiveMessage(ma);
processor.ReceiveMessage(mb);
Assert.AreEqual(ma.Handled, true);
Assert.AreEqual(mb.Handled, true);
}
}
而且我们需要修改注册,如果选择手动注册离子,我们做如下:
public TestSelector()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<MessageAHandler>().As<IMessageHandler<MessageA>>();
containerBuilder.RegisterType<MessageBHandler>().As<IMessageHandler<MessageB>>();
containerBuilder.RegisterType<MessageHandlerAdapter<MessageA>>().As<IMessageHandler>();
containerBuilder.RegisterType<MessageHandlerAdapter<MessageB>>().As<IMessageHandler>();
containerBuilder.RegisterType<MessageReceiver>();
this.container = containerBuilder.Build();
}
在这里,我们现在需要注册一个处理程序和相关的适配器。
它也当然可以进行组装扫描,但这需要多一点点的细节问题,因为使用:
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(x => x.IsAssignableFrom(typeof(IMessageHandler<IMessage>)))
.InstancePerDependency().AsImplementedInterfaces();
将无法正常工作
typeof(MessageAHandler).IsAssignableFrom(typeof(IMessageHandler<IMessage>))
将返回false,因为MessageAHandler实现IMessageHandler,而不是IMessageHandler
要做自动发现和注册,这里是一个片段:
public TestSelector()
{
var containerBuilder = new ContainerBuilder();
Func<Type, Type> GetHandlerInterface = (t) => t.GetInterfaces()
.Where(iface => iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IMessageHandler<>)).FirstOrDefault();
var handlerTypes = typeof(IMessage).Assembly.GetTypes()
.Where(type => type.IsClass
&& !type.IsAbstract
&& GetHandlerInterface(type) != null);
foreach (Type handlerType in handlerTypes)
{
Type messageType = GetHandlerInterface(handlerType).GetGenericArguments()[0];
var genericHandler = typeof(MessageHandlerAdapter<>).MakeGenericType(messageType);
containerBuilder.RegisterType(handlerType).AsImplementedInterfaces();
containerBuilder.RegisterType(genericHandler).As<IMessageHandler>();
}
containerBuilder.RegisterType<MessageReceiver>();
this.container = containerBuilder.Build();
}
如果我理解正确,你有每个消息的工厂?您可以使用IIndex(http://docs.autofac.org/en/latest/advanced/keyed-services.html) –
MHGameWork
2014-11-15 13:19:30
此外,这可能有所帮助:http://stackoverflow.com/questions/25003048/keyed-delegate-factories-with-runtime-constructor-parameters – MHGameWork 2014-11-15 13:20:45
是的,我有一个每个消息处理程序的工厂(每个消息类型有一个消息处理程序)。感谢您的链接。 – fgauna 2014-11-16 16:41:19