创建一个处理多个事件类型的事件处理程序

本文关键字:类型 事件 事件处理 程序 处理 一个 创建 | 更新日期: 2023-09-27 17:58:06

我今天浏览了一些旧代码,发现了一个如下所示的事件处理程序:

public void HandleEvent(EventClassA eventObj)
{
    if(eventObj is EventSubClassA)
    {
        HandleEventSubClassA(eventObj as EventSubClassA);
    }
    else if(eventObj is EventSubClassB)
    {
        HandleEventSubClassB(eventObj as EventSubClassB);
    }
    else if(eventObj.GetType() == typeof(EventSubClassC))
    {
        HandleEventSubClassC(eventObj as EventSubClassC);
    }
    else if(eventObj is EventSubClassD)
    {
        HandleEventSubClassD(eventObj as EventSubClassD);
    }
}

我觉得这有点难看。所以我这样重构它:

delegate void EventHandler(dynamic eventObj);
private static readonly Dictionary<Type, EventHandler> EVENT_MAP = new Dictionary<Type, EventHandler>()
    {
        { typeof(EventSubClassA), HandleEventSubClassA },
        { typeof(EventSubClassB), HandleEventSubClassB },
        { typeof(EventSubClassC), HandleEventSubClassC },
        { typeof(EventSubClassD), HandleEventSubClassD }
    };
public void HandleEvent(EventClassA eventObj)
{
    EVENT_MAP[eventObj.GetType()](eventObj);
}
private void HandleEventSubClassA(dynamic evt)
{
    var eventObj = evt as EventSubClassA;
}

我让一位同事审阅了代码,与以前的解决方案相比,这个解决方案的工作方式令人担忧。我很难相信前面的解决方案是这种情况下的最佳解决方案,所以我转向了StackOverflow。

有没有更好的方法来构建这种类型的类?有没有我不知道的图案是为这个设计的?

创建一个处理多个事件类型的事件处理程序

您可以使用泛型来使现有解决方案稍微安全一点:

private static Dictionary<Type, Delegate> handlers;
static HandlerClass()
{
    handlers = new Dictionary<Type, Delegate>();
    AddHandler<EventSubClassA>(HandleEventSubClassA);
    AddHandler<EventSubClassB>(HandleEventSubClassB);
    ...
}
public static void AddHandler<T>(Action<T> handler) where T : EventClassA
{
    handlers[typeof(T)] = handler;
}
public void HandleEvent(EventClassA @event)
{
    Delegate handler;
    if(handlers.TryGetValue(@event.GetType(), out handler))
    {
        handler.DynamicInvoke(@event);
    }
}

或者,如果您可以修改事件层次结构中的类,则可以实现访问者模式:

public interface IHandlers
{
    void HandleSubClassA(EventSubClassA a);
    void HandleSubClassB(EventSubClassB b);
    ...
}
public abstract class EventClassA
{
    public abstract void Visit(IHandlers handlers);
}
public class EventSubClassA : EventClassA
{
    public override void Visit(IHandlers handlers)
    {
        handlers.HandleSubClassA(this);
    }
}

我觉得我错过了什么。最好的方法不是为每种事件类型编写重载吗?