2013-02-05 136 views
4

我通過一些舊代碼,今天看,發現一個事件處理程序是這樣的:我認爲這是一種醜陋創建的事件處理程序處理多個事件類型

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。

有沒有更好的方法來建立這種類型的? 有沒有一種模式我不知道是專門爲此設計的?

+3

數據輸入'dynamic'非常慢。 「對象」的拳擊方式更快。 – bash0r

+0

似乎很容易通過調用每個子類型並查看發生了什麼來進行單元測試。 –

+0

我沒有意識到'dynamic'和'object'之間存在那種速度差異。謝謝。 – Chris

回答

3

您可以使用仿製藥,使您現有的解決方案就更安全:

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); 
    } 
} 
1

我覺得我失去了一些東西。 對於每種事件類型,寫入重載不是最好的方法嗎?

+0

由於傳入的參數已經被轉換爲基類:否,這在這裏沒有幫助。 –