首先我會爲你的消息,只是一個基本的處理標記一個小的實現,爲了測試
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