基于类型的消息分发实现

在陈硕的github中看到一段非常有意思的代码,可以实现根据消息类型分发到不同的回调函数(link)。代码里是用的Protobuf的反射,本文使用支持多基类的C++类反射实现文中的的反射来改写一下。

首先来定义接口,如果是下面的用例,使用一个类名为key,callback函数为value的hash表就很容易的实现了:


  
class Foo : public Object {}; void OnRecvFoo(Object * foo); dispatcher.Register( " Foo " , OnRecvFoo);

但是这样在OnRecvFoo中需要做类型转换,调用Register时也需要手动输入类名字符串,容易出错且麻烦,所以有了如下用例:


  
void OnRecvFoo(Foo * foo); dispatcher.Register < Foo > (OnRecvFoo);

下面来分析一下实现,首先定义接口:


  
class ObjectDispatcher { public : template < typename T > void Register( const CallbackFunc < T >& func); void OnReceive(Object * obj) const ; };

Register使用带有模板参数的回调函数作为参数,底层消息系统调用OnReceive来分发消息。为了实现注册分发,需要建立一个hash表,key是消息的类型信息,value是带有模板参数的回调函数。由于value类型并不一致,为了放到hash表中,需要定义一个共同基类:


  
class ReceiveCallback { public : virtual ~ ReceiveCallback() {}; virtual void OnReceive(Object * obj) = 0 ; };

然后定义一个带模板参数的派生类表示回调函数:


  
template < typename T > class ReceiveCallbackT : public ReceiveCallback { public : typedef boost::function < void (T * ) > ObjectCallbackFunc; ReceiveCallbackT( const ObjectCallbackFunc & func) : m_func(func) { } virtual void OnReceive(Object * obj) { T * obj1 = dynamic_cast < T *> (obj); assert(obj1 != NULL); m_func(obj1); } protected : ObjectCallbackFunc m_func; };

在Dispatcher中添加一个hash表存储对应关系,并定义一个默认回调函数用于处理没有注册的消息:


  
class ObjectDispatcher { public : ObjectDispatcher() : m_default_callback(boost::bind( & ObjectDispatcher::DefaultObjectCallback, this , _1)) { } template < typename T > void Register( const typename ReceiveCallbackT < T > ::ObjectCallbackFunc & func) { if (m_callbacks.count( & T::ms_classInfo) != 0 ) wximpl::LOG_INFO( " ObjectDispatcher.Connect twice: %s. " , T::ms_classInfo.GetClassName().c_str()); boost::shared_ptr < ReceiveCallbackT < T > > pc( new ReceiveCallbackT < T > (func)); m_callbacks[ & T::ms_classInfo] = pc; } void OnReceive(Object * obj) const { CallbackMap::const_iterator itor = m_callbacks.find(obj -> GetClassInfo()); if (itor != m_callbacks.end()) { itor -> second -> OnReceive(obj); } else { m_default_callback(obj); } } void DefaultObjectCallback(Object * obj) { wximpl::LOG_INFO( " UnProcessed object :%s. " , obj -> GetClassInfo() -> GetClassName().c_str()); } private : typedef std::map < const reflection::ClassInfo < Object >* , boost::shared_ptr < ReceiveCallback > > CallbackMap; CallbackMap m_callbacks; boost::function < void (Object * ) > m_default_callback; };

这样的消息分发机制在一些通信系统中非常实用。

转载于:https://www.cnblogs.com/xiao-liang/p/3566102.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值