我目前正在使用此模式来处理来自某个事件接收器的事件(例如,企业服务总线,队列,EventStore)。这个想法是在列表中实例化几个IEventWorkers(参见下面的具体示例)并传递事件,例如,通过在循环遍历列表时调用每个实例的HandleEvent方法。这是IEventWorkers具体的基本代码:
public class EventWorker : IEventWorker
{
private Dictionary<Type, Action<object>> CreateEventHandlerMapping()
{
return new Dictionary<Type, Action<object>>
{
{typeof (Event1), o => Handle(o as Event1)},
{typeof (Event2), o => Handle(o as Event2)},
};
}
private void Handle(Event1 eventToHandle)
{
}
private void Handle(Event2 eventToHandle)
{
}
public void HandleEvent(IEvent evt)
{
var eventType = evt.GetType();
if (_eventHandlerMapping.ContainsKey(eventType))
{
_eventHandlerMapping[eventType](evt);
}
}
}
也许有更好的方法可以做到这一点?
PS:
This非常接近我想要实现的目标。我不完全理解ObserverRegistry如何分配来自例如事件队列的所有事件。
答案 0 :(得分:1)
你的问题性质相当广泛;也许有点太多了。我鼓励你改进它。
但是,你要求潜在的改进,我至少可以想到一件具体的事情:
有关详细信息,请参阅the visitor pattern。在您的情况下,您可以在Accept
上创建一个类似IEvent
的方法,并在HandleEvent
中调用它:
public void HandleEvent(IEvent evt)
{
evt.Accept(this);
}
接受事件类型的方法如下:
public void Accept(IEventWorker worker)
{
worker.Handle(this);
}
(当然这仍然是一个虚拟调用,请注意现在静态选择处理程序方法重载。这与您现有的运行时字典查找形成对比。)
IEventWorker
接口将强制每个事件类型的方法,这相当于&#34;注册&#34;他们,虽然这次是以类型安全的方式。请注意,这会改变其实施的访问级别,这很好。
然后您可以完全删除映射字典;你现在正在使用该类的虚拟表来达到同样的效果。
我不会继续声称性能改进(如果它在你的场景中更重要),但是如果它很重要你可能想要测试并看到(你应该至少期望更好的性能)。