C++反射的⼀种实现⽅法详解
⼀、注册辅助类
ClassRegistry:模板函数,⽤于data、module、contextdata的注册,其中的函数解析:
create_object:从RegistryMap⾥到传⼊name对应的RegistryNode(RegistryNode保存了名字和构造函数),调⽤构造函数返回。
register_class:⽤传⼊的name和constructor注册RegistryMap,只在Register的构造函数⾥⾯调⽤,后⾯会在ClassRegister<IData> DataRegister、ClassRegister<IModule> ModuleRegister、ClassRegister<IContextData> 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<data_class>(#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<module_class>(#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<data_class>(#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<argument_type<void(VT)>::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))
使⽤:
construct用法在上下⽂相关的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函数。
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,谢谢⼤家对的⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论