如何在C++中实现反射-创新互联

本篇文章为大家展示了如何在C++中实现反射,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

创新互联是网站建设专家,致力于互联网品牌建设与网络营销,专业领域包括网站制作、网站建设、电商网站制作开发、微信小程序定制开发、微信营销、系统平台开发,与其他网站设计及系统开发公司不同,我们的整合解决方案结合了恒基网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,且不断评估并优化我们的方案,为客户提供全方位的互联网品牌整合方案!

一、注册辅助类

ClassRegistry:模板函数,用于data、module、contextdata的注册,其中的函数解析:

create_object:从RegistryMap里找到传入name对应的RegistryNode(RegistryNode保存了名字和构造函数),调用构造函数返回。

register_class:用传入的name和constructor注册RegistryMap,只在Register的构造函数里面调用,后面会在ClassRegister DataRegister、ClassRegister ModuleRegister、ClassRegister ContextDataRegister用到。RegistryMap里面的数据是从register_class这个方法插入数据进去的,后面会在IMPLEMENT_XXX中调用到这个。

fill_name_array:找到RegistryMap里面注册的name,插入传入参数。

二、使用到的宏定义

2.1 data

REGISTER_DATA:声明构造data_class的函数 __construct_##name##_data() ,其中调用了data_calss的构造函数;
声明获取class的get_##name,函数体的get_data从 sign_data_map里面获取到对应的IData

#define REGISTER_DATA(data_class, name)          \
 inline ::wmf::IData* __construct_##name##_data() { return new data_class; } \
 namespace wmf {                \
 namespace internal {              \
 inline data_class* get_##name() { return get_data(#name); }  \
 }                   \
 } // wmf::internal

IMPLEMENT_DATA:调用DataRegister的构造函数。声明变量__##name##_module_register,这里会将输入的name和构造函数__construct_##name##_data注册到RegistryMap中;

#define IMPLEMENT_DATA(name)        \
 ::wmf::internal::DataRegister __##name##_module_register( \
  #name, __construct_##name##_data)

使用:

在需要用到的.cpp文件的的.h文件的位置调用REGISTER_DATA,声明构造函数和获取data的get_xxx函数。

在每个service的cpp文件视线中调用IMPLEMENT_DATA,注入RegistryMap。

在每个service的cpp文件的InitInjection中,INJECT_DATA_MODULE_DEPENDENCY把这个词典注入到module中。

2.2 module

REGISTER_MODULE:声明__construct_#name##_module(),返回new module_class;

声明获取class的get_##name,函数体里面返回ModuleMap中保存的对象(cast_module从ModuleMap里面找到其对应的对象,如果找不到,则从RegisterMap里面找到其构造函数,并调用create_object之后插入ModuleMap,并返回新建的对象(RegisterMap里面的数据从IMPLEMENT_XXX来的))

#define REGISTER_MODULE(module_class, name)    \
 inline ::wmf::IModule* __construct_##name##_module() { \
 return new module_class;        \
 }              \
 namespace wmf {          \
 namespace internal {         \
 inline module_class* get_##name(::wmf::Context& ctx) { \
 return ctx.cast_module(#name);   \
 }              \
 }              \
 } // wmf::internal

IMPLEMENT_MODULE:声明__##name##_module_register变量,以插入RegistryMap。

#define IMPLEMENT_MODULE(name)        \
 ::wmf::internal::ModuleRegister __##name##_module_register( \
  #name, __construct_##name##_module)

使用:

在新增module的.h文件最后调用REGISTER_MODULE声明了在IMPLEMENT_MODULE中会用到的构造函数,以及声明了从ModuleMap中获取其对象的get_xxx函数。

在service的最后调用IMPLEMENT_MODULE,把module注册到RegistryMap中。

2.3 context data

REGISTER_CONTEXT_DATA:声明__construct_##name##_context_data(),新建data_class;

声明获取class的get_##name,函数体里面通过name查找到ContextDataMap保存的名字签名对应的IContextData,转换为data_class返回。

#define REGISTER_CONTEXT_DATA(data_class, name)           \
 inline ::wmf::IContextData* __construct_##name##_context_data() { \
  return new data_class;                     \
 }                                 \
 namespace wmf {                          \
 namespace internal {                       \
 inline data_class* get_##name(const ::wmf::Context& ctx) {    \
  return ctx.cast_context_data(#name);        \
 }                                 \
 }                                 \
 } // wmf::internal

IMPLEMENT_CONTEXT_DATA:声明__##name##_context_data变量,这里会将输入的name和构造函数__construct_##name##_context_data注册到RegistryMap中;

#define IMPLEMENT_CONTEXT_DATA(name)              \
 ::wmf::internal::ContextDataRegister __##name##_context_data( \
   #name, __construct_##name##_context_data)

2.4 index_data

DECLARE_INDEX_DATA:N for name, VT for VersionIndex 类型。声明类型C为用类型VT组装,path、name、desc用N组装的VIAdaptor类型。

#define DECLARE_INDEX_DATA(VT, C, N)                    \
 extern const char __index_##N##_path[];                  \
 extern const char __index_##N##_name[];                  \
 extern const char __index_##N##_desc[];                  \
 typedef wmf::VIAdaptor::type, __index_##N##_path, \
             __index_##N##_name, __index_##N##_desc>      \
   C

DEFINE_INDEX_DATA:N for name,这里是声明一堆string变量,用于data的path、name、desc。

#define DEFINE_INDEX_DATA(N)            \
 const char __index_##N##_path[] = #N "_path";   \
 const char __index_##N##_name[] = #N "_name";   \
 const char __index_##N##_desc[] = #N "_desc";   \
 DEFINE_string(N##_path, "", "index " #N " path"); \
 DEFINE_string(N##_name, "", "index " #N " name"); \
 DEFINE_string(N##_desc, "index_" #N, "index " #N " desc")

2.5 injection

DEFINE_INJECTION:定义一个把object_ref变量设置为class_type*类型的传入变量的函数。

#define DEFINE_INJECTION(injection_name, class_type, object_ref) \
 void set_##injection_name(class_type* module) { object_ref = module; }

INJECT_OBJECT_OBJECT_DEPENDENCY:调用object_to这个对象的set_##injection_name方法,传入参数是object_from的引用。结合DEFINE_INJECTION就是把object_from设置到object_to这个对象里面。

#define INJECT_OBJECT_OBJECT_DEPENDENCY(injection_name, object_from, \
                    object_to)          \
 (object_to).set_##injection_name(&(object_from))

INJECT_MODULE_DEPENDENCY:在上下文context中找到module_from的变量,注入到同一个上下文的module_from里面。

#define INJECT_MODULE_DEPENDENCY(injection_point, context, module_from, \
                 module_to)               \
 ::wmf::internal::get_##module_to(context)->set_##injection_point(   \
   ::wmf::internal::get_##module_from(context));

INJECT_DATA_MODULE_DEPENDENCY:把data注入到通过上下文context获取的module_to中。

#define INJECT_DATA_MODULE_DEPENDENCY(injection_point, context, data, \
                   module_to)           \
 ::wmf::internal::get_##module_to(context)->set_##injection_point(  \
   ::wmf::internal::get_##data());

INJECT_MODULE_OBJECT_DEPENDENCY:通过上下文context获取的module_from注入到object_to中。

#define INJECT_MODULE_OBJECT_DEPENDENCY(injection_point, context, module_from, \
                    object_to)               \
 (object_to).set_##injection_point(                      \
   ::wmf::internal::get_##module_from(context));

INJECT_OBJECT_MODULE_DEPENDENCY :object_from注入到通过上下文获取的module_to中。

#define INJECT_OBJECT_MODULE_DEPENDENCY(injection_point, context, object_from, \
                    module_to)               \
 ::wmf::internal::get_##module_to(context)->set_##injection_point(      \
   &(object_from))

使用:

在上下文相关的session中调用INJECT_MODULE_DEPENDENCY、INJECT_DATA_MODULE_DEPENDENCY;

INJECT_MODULE_DEPENDENCY用于把session相关的信息(比如session_docs、request、response)注入到module中,module的意思是这个请求需要过的模块名。

INJECT_DATA_MODULE_DEPENDENCY用于把data注入到module中。

三、总结

3.1 新增一个module

在新增module的.h文件最后调用REGISTER_MODULE声明了在IMPLEMENT_MODULE中会用到的构造函数,以及声明了从ModuleMap中获取其对象的get_xxx函数。

在service的最后调用IMPLEMENT_MODULE,把module注册到RegistryMap中。

在上下文相关的session中调用INJECT_MODULE_DEPENDENCY、INJECT_DATA_MODULE_DEPENDENCY;

INJECT_MODULE_DEPENDENCY用于把session相关的信息(比如session_docs、request、response)注入到module中,module的意思是这个请求需要过的模块名。

INJECT_DATA_MODULE_DEPENDENCY用于把data注入到module中。

3.2 代码回顾

ClassRegistry用于给第二项的一堆宏使用。module于类的映射关键在于RegistryMap,新增一个module的时候,服务会去RegistryMap里面找名字对应的构造函数。RegistryMap里面的数据是在IMPLEMENT_MODULE的时候注入进来的name和类的对应关系。配置文件里面配的是module的链条,比如需要过AModule,BModule,这时候就在init的时候把所有module都插进去,然后在schedule_impl里面调用每个module的run函数。

上述内容就是如何在C++中实现反射,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联网站建设公司行业资讯频道。

另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享标题:如何在C++中实现反射-创新互联
文章源于:http://myzitong.com/article/djihcp.html