上で見たようにプロキシとしてWindowsランタイム・コンポーネントを作成するメリットは、機械的にプログラムが生成できることだ。
その一方、元のCライブラリの機能の一部のみを使いたい場合には、このやり方はオーバースペックであり、コンポーネントの利用側にとっては学習コストが高くなる。
また、Windowsランタイム・コンポーネント固有の技術的問題として、ソースを自動生成した場合の常道であるジェネレーション・ギャップ・パターン(=自動生成されたコードを直接利用せずに、そこから派生クラスを作成して、派生クラスに手を入れることでソースの生成と利用を独立させ、コードの保守性を高める手法)が適用できないため、工夫が必要となる。
例えば、上の例のMrbクラスに相当するコードを「MrbDirect」という名称で自動生成した場合に、ジェネレーション・ギャップを埋めるためのサブクラス「Mrb」をかぶせる方法について考えてみよう。Windowsランタイム・コンポーネントとしてABIを備えるのはサブクラスのMrbクラスのほうだ。
つまり、次のようなファイル構成を取るのが目標となる。
// mrbgen.h
ref class MrbDirect
{
public:
自動生成したコード
}
// mrb.h
public ref class Mrb selaed : MrbDirect
{
追加のコード
}
まず、上のコードはコンパイルできない。というのは、mrbgen.hファイルはアセンブリ参照対象だが、クラスがpublicではないため、C3213となるからだ。
そこで、次のようにMrbDirectクラスをpublicなクラスとしてみよう*1。
*1 外部へインターフェイスを公開したくないクラスをpublicにせざるを得ない点で、すでにダメという結論は出てしまうのだが、ここではそれについては無視する。
public ref class MrbDirect
{
……
}
これはコンパイル・エラーC4585となる。public refクラスはsealedの必要があるからだ。
そこでさらに次のように修正する。
public ref class MrbDirect sealed
{
……
}
もちろん、sealedクラスは継承できないので、今度はmrb.hファイルでコンパイル・エラーC3246となる。
結局、ジェネレーション・ギャップ・パターンはC++/CXのWindowsランタイム型クラスには適用できない。もっとも、サブクラスではなく、自動生成したクラスを内包するクラスとして実装することは可能だ。ただし、そうすると、クライアント→ランタイム型クラス→自動生成したプロキシ→再利用対象クラス、と委譲の委譲となってしまう。さすがにそこまでする価値があるとは考えにくいため、自動生成したクラスを直接手修正する方法を取ることになるだろう。
Copyright© Digital Advantage Corp. All Rights Reserved.