最近又准备蠢蠢欲动开始写Sql的ORM了。但是ORM遇到的第一个问题就是C++没有反射!!!!。用过Java的同学都知道,使用Java的反射就能实现简单的ORM功能。奈何C++没有,只能自己实现一下了。主要实现代码如下:
https://github.com/wangsun1983/Obotcha/blob/master/lang/include/Reflect.hpp
代码中主要的宏定义就是:DECLARE_REFLECT_FIELD
#define DECLARE_REFLECT_FIELD(CLASS, ...) \
std::map<std::string,std::function<void(std::string) >> mSetMaps;\
IMPLE_SET_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__) \
void __ReflectInit() {\
IMPLE_INIT_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__)\
}\
void setFieldValue(String field,String value) {\
mSetMaps[field->getStdString()](value->getStdString());\
}\
- 使用方法:在类声明中加入类似这样的宏定义DECLARE_REFLECT_FIELD(类名,变量名1,变量名2,....)示例代码如下:
#define DECLARE_REFLECT_FIELD(CLASS, ...) \ std::map<std::string,std::function<void(std::string) >> mSetMaps;\ IMPLE_SET_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__) \ void __ReflectInit() {\ IMPLE_INIT_FUNCTION_DETECT(_##CLASS,GET_ARG_COUNT(__VA_ARGS__),__VA_ARGS__)\ }\ void setFieldValue(String field,String value) {\ mSetMaps[field->getStdString()](value->getStdString());\ }\
- mSetMaps用来存放变量名字和变量设定函数的键值对,其中设定函数暂时统一使用:std::function<void(std::string)>。实际上的变量设定函数是通过一个宏去实现的,可以看到这个函数实际上就是void(std::string):
#define IMPLE_SET_VALUE_1(CLASS,MEMBER) \ void __ReflectSet##MEMBER(std::string v) { \ std::stringstream iss(v);\ iss>>this->MEMBER;\ }
- IMPLE_SET_FUNCTION_DETECT会遍历DECLARE_REFLECT_FIELD中传入了所有变量,逐个生成每个变量的设定函数。
-
__ReflectInit这个函数会在Object创建的时候被调用一次,自动把IMPLE_SET_FUNCTION_DETECT生成的设定函数和变量名存入mSetMaps。这个是Obotcha中创建实例的create函数实现,为了反射,我们在实例创建后多加入了__ReflectInit的调用。
#define MAKE_FUNCTION_0(Y) \ template<typename... Args>\ sp<_##Y> create##Y(Args&&... args)\ {\ Object* obj = new _##Y(std::forward<Args>(args)...);\ obj->__ReflectInit();\ sp<_##Y> ret;\ ret.set_pointer(dynamic_cast<_##Y *>(obj));\ return ret;\ }\
-
setFieldValue就是类似Java反射的设定函数。
完成这些修改后,我们就可以愉快的使用反射了。先来看一下简单的json反射成class实例的代码:
DECLARE_SIMPLE_CLASS(MyReflectData) {
public:
int a;
double d;
DECLARE_REFLECT_FIELD(MyReflectData,a,d)
};
int testreflect() {
JsonReader mReader = createJsonReader(createFile("reflect.json"));
MyReflectData data = mReader->reflect<st(MyReflectData)>();
std::cout<<"a is "<<data->a<<";d is "<<data->d;
}