2

我目前正在使用这种模式来处理来自某个事件接收器(例如企业服务总线、队列、EventStore)的事件。这个想法是在一个列表中实例化几个 IEventWorker(参见下面的具体示例)并传递事件,例如,通过调用每个实例的 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:

与我想要实现的目标非常接近。我不完全理解 ObserverRegistry 将如何工作以分发来自例如事件队列的所有事件。

4

1 回答 1

1

您的问题本质上很广泛;也许有点太多了。我鼓励你完善它。

但是,您要求潜在的改进,我至少可以想到一件足够具体的事情:

  • 您可以使用双重调度而不是类型转换来确保类型安全。

有关更多信息,请参阅访问者模式。在您的情况下,您将创建一个Accept-like 方法IEvent并在以下位置调用它HandleEvent

public void HandleEvent(IEvent evt)
{
    evt.Accept(this);
}

事件类型的接受方法如下所示:

public void Accept(IEventWorker worker)
{
    worker.Handle(this);
}

(虽然这当然仍然是一个虚拟调用,但请注意处理程序方法重载现在是静态选择的。这与您现有的运行时字典查找形成对比。)

IEventWorker接口将要求每个事件类型有一个方法,这相当于“注册”它们,尽管这次是以类型安全的方式。请注意,这会改变他们在您的实现中的访问级别,这很好。

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

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

于 2016-02-04T09:39:51.017 回答