ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[COM] COM モニカと表示名の概念

 
モニカとは COM で DI(Dependency Injection) を実現するための機構と言えるだろう。


モニカと表示名

表示名とモニカ・オブジェクトは一対のもの。
表示名は、任意のオブジェクトの識別するための名前。特定の構文を持つ。
モニカ・オブジェクトは、表示名が識別するオブジェクトにバインドするオブジェクト。

各々の表示名に対して、各々のモニカ・オブジェクトが対応する。

例 ファイルモニカ
識別されるオブジェクト
ファイルに永続化されたオブジェクト

表示名
c:tmpursus.obj

モニカ・オブジェクト
ファイルモニカのインスタンス



モニカを使ってオブジェクトをバインドする典型的な手順
  1. MkParseDisplayName を呼び出し、表示名から、表示名に対応するモニカ・オブジェクトを取得
  2. モニカ・オブジェクトのIMoniker::BindToObject を呼び出し、対象のオブジェクトをバインドする。


クラスモニカについて

クラスモニカの何が有り難いんだ、直接、CoGetClassObject を呼び出せばいいじゃないか、という疑問に対して。。

利点のひとつは、Inside DCOM に書かれていたとおり、Visual Basic でカスタム クラス オブジェクトにアクセスできること。
そもそもの意義としては、統一的なやり方でオブジェクトを取得できるということ。モニカは、オブジェクトの名前解決の標準メカニズムである。クラスオブジェクトもCOMオブジェクトである。そのクラスオブジェクトでさえ、普通のCOMオブジェクトとして、上に記した典型的な手順で取得できる。

[サイト紹介] ソースコード 色づけ サイト

 
ソースコードを色付けるサイト
source code highlight で検索してみよう。

-- ソースコード 色付け サイト --
VimColor - source code highlight
http://vimcolor.spiritloose.net/

Source Code Highlighter
http://source.virtser.net/

[未分類] ORACLE PL/SQL 結合配列 FOR ループ

 
DECLARE

TYPE TDICTIONARY IS TABLE OF INT INDEX BY VARCHAR2(100);
dict TDICTIONARY;
key VARCHAR2(100);

BEGIN
dict('DEF') := 2;
dict('HIJ') := 1;
dict('ABC') := 3;

key := dict.FIRST;
WHILE key IS NOT NULL LOOP
    DBMS_OUTPUT.PUT_LINE(dict(key));
    key := dict.NEXT(key);
END LOOP;
END;
/
という具合に。。

[Inside COM] Inside COM 第8章 コンポーネントの再利用:包含と集約(その2)

 
外側のコンポーネントが非委譲unknownやそのほかの内側のコンポーネントに属するインターフェースを要求すると、外側のコンポーネントの参照カウントがインクリメントされている。これは、クライアントが内側のコンポーネントに属するインタフェースを要求したときは理想的な展開である。
Inside COM 163頁 8.3.5

下線部の "非委譲unknownや" の記述に問題がある。
NondelegatingQueryInterface の実装を確認すると、
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid,
                                                  void** ppv)
{     
    if (iid == IID_IUnknown)
    {
        // !!! CAST IS VERY IMPORTANT !!!
        *ppv = static_cast<INondelegatingUnknown*>(this) ;
    }
    else if (iid == IID_IY)
    {
        *ppv = static_cast<IY*>(this) ;
    }
    else
    {
        *ppv = NULL ;
        return E_NOINTERFACE ;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
    return S_OK ;
}
Inside COM 158-159頁 8.3.3

下から3行目の AddRef() の呼び出しで、委譲AddRef を呼び出し、外側のコンポーネントの参照カウントをインクリメントしているように見える。
しかし、reinterpret_cast<IUnknown*>(*ppv) のキャストに注目して欲しい。
IID_IUnknown が要求された場合、ppv は、 static_cast<INondelegatingUnknown*>(this) となり、AddRef() 呼び出しは、 reinterpret_cast によって、NondelegatingAddRef() が呼び出されるのではあるまいか。
したがって、「外側のコンポーネントが非委譲unknownやそのほかの内側のコンポーネントに属するインターフェースを要求すると」の非委譲unknown を要求した場合に限っては内側のコンポーネントの参照カウントがインクリメントされるのではないか。一方、要求されたインタフェースが非委譲unknown でなければ、IUnknown を継承しているはずなので、委譲AddRefが呼ばれるだろう。

ところで、クライアントが内側のインタフェースを要求するとき、なぜ、内側の参照カウントではなく外側の参照カウントがインクリメントされることが理想的なのか。
この理由は、内側のコンポーネントの生存期間は、外側のコンポーネントの生存期間に包括されるという寿命管理の要件にある。集約オブジェクトの寿命管理では、外側のコンポーネントがディアクティベートされたら、内側のコンポーネントもディアクティベートされるべきである。

もし、クライアントが、内側のコンポーネントの参照カウントを直接制御するAddRef、Release を呼び出すとしたらどうなるか。そうすると、外側のコンポーネントの関知しないところで、内側のコンポーネントの寿命管理が行われることになる。これではまずい。
したがって、外側のコンポーネントは、内側のコンポーネントについてAddRef、Release による参照/解除の通知を必要とする。