我一直在開發一些遊戲的不同事件系統,其中偵聽器接收到通用事件類型對象,並且必須將其真實類型與開關或類似對象進行區分,然後將其轉換爲正確的子類事件。字典上的C#代表的逆變問題
不同aproaches我能後襬脫使用結構的開關情況如下(簡化):
public class Event {}
public class EventA : Event {}
public class EventB : Event {}
public delegate void HanlderDelegate(Event ev);
public class EventManager
{
Dictionary<Type, HanlderDelegate> delegateMap = new Dictionary<Type, HanlderDelegate>();
public void Dispatch(Event ev)
{
if (delegateMap.ContainsKey(ev.GetType()))
{
delegateMap[ev.GetType()].Invoke(ev);
}
}
public void Register<T>(HanlderDelegate handler) where T : Event
{
delegateMap.Add(typeof(T), handler);
}
}
public class EventListener
{
public EventListener(EventManager evtMgr)
{
evtMgr.Register<EventA>(this.HandleEventA);
evtMgr.Register<EventB>(this.HandleEventB);
}
public void HandleEventA(Event ev)
{
EventA evA = (EventA)ev;
//... do stuff
}
public void HandleEventB(Event ev)
{
EventB evB = (EventB)ev;
//... do stuff
}
}
我這種做法很高興,但我還是找到了鑄件每種方法都可以改進。我試圖讓代表更通用
public delegate void HanlderDelegate<T>(T ev) where T : Event;
因此聽衆可以直接執行public void HandleEvent(EventA ev)
和public void HandleEvent(EventB ev)
並註冊它們。
但是,當然,EventManager類中的字典應該存儲指向HanlderDelegate<Event>
的指針,並且存在問題開始的地方,我不能將HanlderDelegate<EventA>
轉換爲HanlderDelegate<Event>
以存儲它們,並且同時以另一種方式調用它以調用它們。
有沒有辦法做到這一點?我知道編譯器會允許奇怪的東西,但是我知道它,並且可以通過代碼控制EventB沒有被錯誤地輸出到EventA等等。
在此先感謝!
謝謝,托馬斯!在字典中使用類型委託允許代表是通用的並解決該部分。從來沒有遇到過。我也注意到Delegate類可以調用DynamicInvoke而不需要強制轉換。有沒有什麼區別,比如表演等等?因爲設置Dispatch方法通用限制了可能性,例如在分派所有事件之前排隊所有事件。 –