通过多个使用者和事件处理程序使用存储的事件

本文关键字:存储 事件 程序 事件处理 使用者 | 更新日期: 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接口将为每个事件类型强制使用一种方法,这相当于"注册"它们,尽管这次是以类型安全的方式。请注意,这会更改他们在实现中的访问级别,这很好。

然后,您可以完全删除映射字典;您现在正在使用类的虚拟表来实现相同的效果。

我不会继续声称性能改进(如果它在您的场景中很重要(,但如果它很重要,您可能想要测试和查看(您至少应该期待更好的性能(。