我有一组消息,都来自Message,并实现了IMessage接口:
class Message : IMessage
{
public string example1;
}
class LogOnMessage : Message
{
public string password;
}
class LogOffMessage : Message
{
public string anotherExample;
}
我有一个消息传递系统,其中代理能够检测传入的消息,并根据消息的类型运行表单的委托
void MyDelegate(IMessage msg)
这是通过调用这样的处理程序注册函数来完成的:
RegisterHandler(typeof(LogoffMessage),handler)
这个实现只是一个类型的字典,每个条目都是一个处理程序列表:Dictionary< type,list< MyDelegate> >
现在,这一切都很好,但当然处理程序看起来像这样:
void MyHandler(IMessage msg)
{
LogOffMessage lMsg = (LogOffMessage)msg;
string athrEx = lMsg.anotherExample;
//Proceed with handling the logoff
}
现在,这有几个问题。一个是你可能试图将Msg转换为错误的类型。
另一个是,在任何处理程序的前几行中打开所有内容都有点不优雅,而不是像这样的处理程序,我想要:
void MyDelegate(LogOffMessage msg)
你会提出什么建议?
我想的可能不是类型字典,而是可以使用其他结构来使用泛型来保存不同的委托类型。所以会有一个MyDelegate< MsgType>每种类型的清单。但目前尚不清楚如何制作集合集合,其中每个内部集合类型都不同。
答案 0 :(得分:1)
让你的代表通用:
delegate void MessageHandler<T>(T message) where T : IMessage
并使您的RegisterHandler
方法通用:
void RegisterHandler<T>(MessageHandler<T> handler)
然后用以下方法调用它:
RegisterHandler(handler); // Let type inference handle it
RegisterHandler<LogOffMessage>(handler); // State type argument explicitly
然后当你按类型获取委托时,可以将它转换为正确的处理程序类型 - 即使从编译器的角度来看它是“不安全的”,你知道你只会有在词典中添加了正确的处理程序:
// When you populate this, create the appropriate type of
// `List<MessageHandler<T>>` based on the key
private Dictionary<Type, object> handlerMap;
void CallHandlers<T>(T message) where T : IMessage
{
object value;
if (handlerMap.TryGetValue(typeof(T), out value))
{
List<MessageHandler<T>> handlers = (List<MessageHandler<T>>) value;
foreach (MessageHandler<T> handler : handlers)
{
handler(message);
}
}
}
请注意,使用List<MessageHandler<T>>
的另一种方法是组合代理,最后在地图中为每种类型添加多播委托。