ダイナミック・バインディング
C++ クラスを生成する代わりに、Dyn_obj クラスを使用すると、動的に Caché クラスを操作できます。したがって、汎用クラスを扱い、特定の Caché クラスに依存しないアプリケーションやツールを記述する際に役立ちます。しかし、この一般的な方法は、C++ コンパイラがコードを静的に分析しないため、パフォーマンスの低下を招きます。プログラムの記述時にどのクラスが必要であるかがわかっている場合は、生成されたクラスを使用することをお勧めします。
Dyn_obj プロキシの構築
他のプロキシと同様に、プロキシ・オブジェクトを生成するために、Dyn_obj は以下のメソッドを持ちます。
static d_ref<Dyn_obj> openref(Database* db,
int ref,
const_name_t type); // const_name_t is a typedef for const wchar_t*
static d_ref<Dyn_obj> create_new(Database* db,
const_name_t type,
const_str_t init_val = 0, // const_str_t is a typedef of const wchar_t*
Db_err* err = 0);
static d_ref<Dyn_obj> open(Database* db,
const d_binary& oid,
int concurrency = -1,
int timeout = -1,
Db_err* err = 0);
static d_ref<Dyn_obj> openid(Database* db,
const_name_t type,
const_str_t id,
int concurrency = -1,
int timeout = -1,
Db_err* err = 0);
生成されたクラスの同じメソッドとこれらとの違いは、クラスの名前に対する追加のパラメータのみです。
さらに、Dyn_obj は init() というメソッドを持ちます。これにより、Dyn_obj の get_property()、run_obj_method()、および run_class_method() の各メソッドの結果から、Dyn_obj インスタンスを構築できます。
static d_ref<Dyn_obj> init(t_istream& in, Database* db);
Dyn_obj メソッドの呼び出しからの値の構築
Dyn_obj メソッドの呼び出しから返されるすべての値は、t_istream (トランスポート入力ストリーム) 内部に返されます。値がデータ型のインスタンスである場合、以下のように t_istream のみから構築することができます。
d_int val(in);
ここで、in は t_istream のタイプです。
値がオブジェクトである場合、t_istream はその OREF とクラス名を含みます。つまり、Database オブジェクトも必要であることを意味します。コンパイル時に返されるオブジェクトのタイプがわかっている場合は、そのタイプの openref() メソッドを使用することもできます。例えば、Sample.Person タイプのオブジェクトが返される場合、そのオブジェクトは以下のように構築できます。
d_ref<Sample_Person> p = Sample_Person::openref(db, d_int(in));
d_int(in) は、OREF を含む一時的な d_int 値を生成し、d_int 値を int に変換します。それ以外の場合は、以下のように構築できます。
d_ref<Dyn_obj> p = Dyn_obj::openref(in, db);
オブジェクトのタイプは、入力ストリームから読み取ります。init() メソッドのシグニチャは、他の D_type インスタンスからのコンストラクタと一致しますが、Database ポインタが 0 でない場合は一致しません。
プロパティとメソッド
一度 Dyn_obj プロキシを構築すると、これを使用してプロパティ値を取得して設定し、クエリを実行し、メソッドを実行することができます。
t_istream& get_property(const_name_t prop_name);
void set_property(const_name_t prop_name, D_type* val);
void get_query(const_name_t query_name, d_query& query) const;
// const_name_t is a typedef for const wchar_t*
メソッドを実行するには、引数へのポインタ (D_type*) の配列と引数の数をそのメソッドに渡す必要があります。以下のように、Database オブジェクトにより割り当てられたバッファを使用できます。
D_type* args[2];
args[0] = &arg1;
args[1] = &arg2;
// code
これは、max_num_obj_args ポインタ (引数の最大許容数) を格納できます。run_obj_method() のシグニチャは、以下のとおりです。
t_istream& run_obj_method(
const_name_t mtd_name, // const_name_t is a typedef for const wchar_t*
D_type** args,
int num_args);
クラス・メソッドを実行するには、以下の run_class_method() を使用できます。
static t_istream& run_class_method(Database* db,
const_name_t cl_name, // const_name_t is a typedef for const wchar_t*
const_name_t mtd_name,
D_type** args,
int num_args);
参照により渡される引数の値は、これらのメソッド内部で変更されます。以下はその例です。
const_name_t cl_name = __NAME_V(Sample.Person);
D_type* args[2];
d_ref<Dyn_obj> p = Dyn_obj::openid(db, cl_name, __STRING_V(1));
// create a proxy
d_string dob(p->get_property(__NAME_V(DOB)));
// get date of birth
d_int arg1(2);
d_int arg2(3);
args[0] = &arg1;
args[1] = &arg2;
d_int res = p->run_obj_method(__NAME_V(Addition), args, 2);
args[0] = &dob;
d_int age =
Dyn_obj::run_class_method(db, cl_name, __NAME_V(CurrAge), args, 1);
d_query by_name(db);
p->get_query(__NAME_V(ByName), by_name);
引数の配列にあるポインタは、一時的な変数を指すことはできません。以下のようなコードは、クラッシュを引き起こす可能性があります。
args[ii] = &d_int(1); // DO NOT USE!