2012-01-07 56 views
2

我正在使用一些.NET框架,它允许注册类型为Action<IMessage>的事件处理程序。通用事件处理

IMessage是接收所有消息的接口。

我希望能够(以某种方式)注册处理程序,了解收到的消息的具体类型,以便更彻底地记录它。

事情与此类似:

manager.Register(SpecialHandler); 

public void SpecialHandler(SpecialMessage msg) 
{ 
    // log. 
} 
  • SpecialMessage是实现即时聊天类型。

这是不可能的,有没有一种简单的方法来做到这一点?

回答

3
// improved version of Travis Gockel's approach 
void Register<T>(Action<T> action, bool invokeOnTypeMismatch = false) 
    where T : IMessage 
{ 
    Action<IMessage> wrapped = (msg) => 
     { 
      if (msg is T) 
      { 
       action((T)msg); 
      } 
      else if (invokeOnTypeMismatch) 
      { 
       action(default(T)); 
      } 
     }; 

    // private Action<IMessage> method = delegate{}; 
    method += wrapped; 
} 
2
class MessageSystem 
{ 
    readonly Dictionary<Type, Action<IMessage>> handlers = new Dictionary<Type, Action<IMessage>>(); 

    public void Register<T>(Action<T> action) where T : IMessage 
    { 
     Action<IMessage> wrapped = (IMessage msg) => action((T)msg); 
     handlers[typeof(T)] = wrapped; 
    } 

    public void Invoke(IMessage msg) 
    { 
     handlers[msg.GetType()](msg); 
    } 
} 
+0

你打我吧! – siride 2012-01-07 23:15:35

+1

@ Travis Gockel:这里的'method'是什么? – Tigran 2012-01-07 23:21:08

+0

如果msg不能转换为T(即,如果注册了两个不同的专用处理程序),这将不起作用 – Nuffin 2012-01-07 23:22:24

1

您可以使用多态这里

元代码:

interface IMessage 
{ 
    void Handle() 
    ... 
} 

class MessageFoo : IMessage 
{ 
    void Handle() 
    { 
     //foo handle 
    } 
} 

class MessageBar : IMessage 
{ 
    void Handle() 
    { 
     //bar handle 
    } 
} 

而这正是你处理它们

class HandlingManager 
{ 
    void HandleMessage(IMessage m) 
    { 
     m.Handle(); //knows which concrete type 
    } 
} 
+0

我喜欢这种方法,但问题是现在你的消息的行为与他们的类型有关。因此,以两种不同的方式处理相同的信息是不可能的(取决于谁在处理它们)。 – 2012-01-07 23:32:39

+0

我不拥有IMessage的代码,因此我不能以这种方式修改它。 – 2012-01-07 23:34:38

0

看看CSharpMessenger Extended

这是一个基于委托的C#事件系统。它使用泛型来实现静态输入。与其他消息传递系统(如CSharpEventManager)一样,它允许事件生产者和事件消费者之间进行消息传递,而无需生产者或消费者相互了解。信使被实现为静态类,所以永远不需要实例化一个信使对象。泛型的使用意味着参数可以是任何类型的,并且不局限于特殊的Message类的子类 - 如果回调只需要一个浮点数然后提供一个浮点数。