通过多个消费者和事件处理程序消费存储的事件

时间:2016-02-04 09:00:38

标签: c# events reactivex

我目前正在使用此模式来处理来自某个事件接收器的事件(例如,企业服务总线,队列,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如何分配来自例如事件队列的所有事件。

1 个答案:

答案 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;他们,虽然这次是以类型安全的方式。请注意,这会改变其实施的访问级别,这很好。

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

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