C++反射の一種の実現方式


テーマC++
一、登録補助類
ClassRegistry:data、module、contextdataの登録に使用されるテンプレート関数.関数の解析:
create_object:RegistryMapから受信nameに対応するRegistryNode(RegistryNodeは名前とコンストラクション関数を保存している)を見つけ、コンストラクション関数を呼び出して返します.
register_class:RegistryMapは、受信したnameとconstructorで登録され、Registerのコンストラクション関数でのみ呼び出され、後でClassRegister Data Register、ClassRegister ModuleRegister、ClassRegister ContextData Registerで使用されます.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

プログラミングを学びたい初心者がいたら、C/C++技術学習ボタンqunに来てください.前は58、93、後ろは4、83-89で、システム全体のC/C++チュートリアルを無料で送ります.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関数
各サービスのcppファイル視線でIMPLEMENT_を呼び出すDATA、RegistryMapを注入します.
各サービスの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関数
サービスの最後に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:コンテキストcontextで取得したmodule_にdataを注入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関数
サービスの最後にIMPLEMENTを呼び出すMODULEは、moduleをRegistryMapに登録します.
コンテキスト関連セッションでINJECT_を呼び出すMODULE_DEPENDENCY、INJECT_DATA_MODULE_DEPENDENCY;
INJECT_MODULE_DEPENDENCYは、session_docs、request、responseなどのsession関連情報をmoduleに注入するために使用され、moduleは、このリクエストに必要なモジュール名を意味する.
INJECT_DATA_MODULE_DEPENDENCYは、dataをmoduleに注入するために使用されます.