2010-08-12 113 views
0

我有一组消息,所有从消息派生,实现接口即时聊天:接口/继承/委托设计问题

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) 

这种情况的实现是简单类型的字典,每个条目是处理程序的列表:字典<类型,列表< 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>列表。但目前还不清楚如何制作集合的集合,其中每种内部集合类型都不同。

回答

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 

然后,当你通过获取代理类型,您可以将其转换为正确的处理程序类型 - 即使它是c中的“不安全”看,ompiler的时候,你知道,你只添加了正确的处理程序到词典:

// 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>>只是结合的代表并与最终多播委托在每个类型的地图。