通过多个使用者和事件处理程序使用存储的事件
本文关键字:存储 事件 程序 事件处理 使用者 | 更新日期: 2023-09-27 18:33:07
我目前正在使用此模式来处理来自某些事件接收器(例如企业服务总线,队列,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);
}
}
}
也许有更好的方法可以做到这一点?
附注:
这与我想要实现的目标非常接近。我不完全理解 ObserverRegistry 如何分发来自事件队列的所有事件。
你的问题在性质上是相当广泛的; 也许有点太多了。我鼓励你改进它。
但是,您要求潜在的改进,我至少可以想到一件足够具体的事情:
- 为了类型安全,可以使用双重调度而不是类型转换。
有关详细信息,请参阅访客模式。在您的情况下,您将在IEvent
上创建一个类似Accept
的方法,并在HandleEvent
中调用它:
public void HandleEvent(IEvent evt)
{
evt.Accept(this);
}
事件类型的接受方法如下所示:
public void Accept(IEventWorker worker)
{
worker.Handle(this);
}
(当然,虽然这仍然是一个虚拟调用,但请注意,现在静态选择了处理程序方法重载。这与现有的运行时字典查找形成对比。
IEventWorker
接口将为每个事件类型强制使用一种方法,这相当于"注册"它们,尽管这次是以类型安全的方式。请注意,这会更改他们在实现中的访问级别,这很好。
然后,您可以完全删除映射字典;您现在正在使用类的虚拟表来实现相同的效果。
我不会继续声称性能改进(如果它在您的场景中很重要(,但如果它很重要,您可能想要测试和查看(您至少应该期待更好的性能(。