我有一个ESB。任何序列化消息都传输其自己的完全限定名称(即命名空间 + 类名)。对于每条消息,我都有一个具体的类型,它封装了要执行的特定逻辑。
每次我收到一条消息,我首先需要反序列化它,这样我才能执行它的操作——再一次,取决于它的具体类型——。
我需要一种在编译时或应用程序初始化期间注册每个类的方法。
使用 .net,我将使用反射来扫描程序集并在初始化期间发现消息类型,但是您将如何在 C++ 中做到这一点?
我有一个ESB。任何序列化消息都传输其自己的完全限定名称(即命名空间 + 类名)。对于每条消息,我都有一个具体的类型,它封装了要执行的特定逻辑。
每次我收到一条消息,我首先需要反序列化它,这样我才能执行它的操作——再一次,取决于它的具体类型——。
我需要一种在编译时或应用程序初始化期间注册每个类的方法。
使用 .net,我将使用反射来扫描程序集并在初始化期间发现消息类型,但是您将如何在 C++ 中做到这一点?
C++ 没有反射能力。我想您可以尝试扫描目标文件等,但是没有可靠的方法可以做到这一点(AFAIK);编译器可能会完全消除或破坏某些东西。
本质上,对于序列化,您必须(半)手动进行注册。但是您可能对有助于处理琐事的序列化库感兴趣,例如Boost Serialization。
由于在 C++ 中没有反射,我建议使用外部脚本来扫描所有相关类的源代码(如果您使用空的虚拟#defines 在源代码中注释它们,这很容易)并让它生成注册代码.
我个人使用手动注册的道路。如果您忘记注册......那么测试无论如何都不起作用。
你只需要使用工厂,并实现一些标签调度。例如:
typedef void (*ActOnMessageType)(Message const&);
typedef std::map<std::string, ActOnMessageType> MessageDispatcherType;
static MessageDispatcherType& GetDispatcher() {
static MessageDispatcherType D; return D;
}
static bool RegisterMessageHandler(std::string name, ActOnMessageType func) {
return GetDispatcher().insert(std::make_pair(name, func)).second;
}
然后你只需准备你的功能:
void ActOnFoo(Message const& m);
void ActOnBar(Message const& m);
并注册它们:
bool const gRegisteredFoo = RegisterMessageHandler("Foo", ActOnFoo);
bool const gRegisteredBar = RegsiterMessageHandler("Bar", ActOnBar);
注意:我有效地使用了一个延迟初始化的 Singleton,以允许解耦。也就是说,注册是在库加载期间完成的,因此每个Register...
调用都放在定义函数的文件中。与全局变量的一个区别是,一旦初始化结束,这里的调度映射实际上是恒定的。