我一直在开发一些游戏的不同事件系统,其中侦听器接收到通用事件类型对象,并且必须将其真实类型与开关或类似对象进行区分,然后将其转换为正确的子类事件。字典上的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方法通用限制了可能性,例如在分派所有事件之前排队所有事件。 –