クラスに対する既定のマーシャリング
更新 : 2007 年 11 月
クラスは、COM 相互運用機能によってだけマーシャリングでき、常にインターフェイスとしてマーシャリングされます。クラスをマーシャリングするために使用されるインターフェイスが、クラス インターフェイスと呼ばれる場合もあります。選択したインターフェイスで、クラス インターフェイスをオーバーライドする方法については、「クラス インターフェイスの概要」を参照してください。
COM へのクラスの引き渡し
マネージ クラスを COM に渡す場合、相互運用マーシャラは自動的に COM プロキシでそのクラスをラップし、そのプロキシによって生成されるクラス インターフェイスを COM メソッド呼び出しに渡します。次に、プロキシは、そのクラス インターフェイスに対するすべての呼び出しの処理をマネージ オブジェクトに任せます。プロキシは、クラスによって明示的に実装されていないその他のインターフェイスも公開します。プロキシは、クラスに代わって IUnknown や IDispatch などのインターフェイスを自動的に実装します。
.NET コードへのクラスの引き渡し
一般に、コクラスは COM におけるメソッド引数としては使用されません。通常は、コクラスの代わりに既定のインターフェイスが渡されます。
マネージ コードにインターフェイスを渡す場合、相互運用マーシャラが適切なラッパーでそのインターフェイスをラップし、そのラッパーをマネージ メソッドに渡します。使用するラッパーを決定することが困難な場合もあります。COM オブジェクトのすべてのインスタンスは、そのオブジェクトが実装するインターフェイスの数とは関係なく、単一で一意のラッパーを持ちます。たとえば、単一の COM オブジェクトが 5 つの異なるインターフェイスを実装している場合でも、そのオブジェクトのラッパーは 1 つだけです。同じラッパーが 5 個すべてのインターフェイスを公開します。この COM オブジェクトのインスタンスを 2 つ作成する場合、同じラッパーのインスタンスが 2 つ作成されます。
ラッパーが有効期間を通じて同じ型を維持するためには、オブジェクトが公開するインターフェイスを相互運用マーシャラを通じて初めて渡すときに、相互運用マーシャラが正しいラッパーを識別する必要があります。マーシャラは、オブジェクトが実装するインターフェイスのいずれかを確認することで、そのオブジェクトを識別します。
たとえば、マーシャラは、マネージ コードに渡されたインターフェイスをラップするために、クラス ラッパーを使用する必要があると判断します。マーシャラを通じて初めてインターフェイスが渡されたときに、マーシャラはそのインターフェイスが既知のオブジェクトから渡されたのかどうかを確認します。この確認は、2 つの状況で実行されます。
インターフェイスが、どこか他の場所で COM に渡された別のマネージ オブジェクトによって実装されている場合。マーシャラは、マネージ オブジェクトによって公開されたインターフェイスをすぐに識別し、そのインターフェイスと実装を提供するマネージ オブジェクトとを対応付けることができます。その後、マネージ オブジェクトがメソッドに渡されるため、ラッパーは必要ありません。
既にラップされているオブジェクトがインターフェイスを実装している場合。このケースに該当するかどうかを判断するために、マーシャラはオブジェクトに対して IUnknown インターフェイスを照会し、返されたインターフェイスを、既にラップされている他のオブジェクトのインターフェイスと比較します。インターフェイスが別のラッパーのインターフェイスと同じ場合、これらのオブジェクトは同じ ID を持つため、既存のラッパーがメソッドに渡されます。
インターフェイスが既知のオブジェクトから渡されたのではない場合、マーシャラは次の処理を実行します。
マーシャラは、IProvideClassInfo2 インターフェイス対してオブジェクトをクエリします。そのインターフェイスが存在している場合、マーシャラは IProvideClassInfo2.GetGUID から返される CLSID を使用して、そのインターフェイスを提供するコクラスを識別します。あらかじめアセンブリが登録されている場合には、この CLSID を使用することで、レジストリからラッパーを特定できます。
インターフェイスに対して IProvideClassInfo インターフェイスを照会します。このインターフェイスが存在している場合は、IProvideClassInfo.GetClassinfo から返される ITypeInfo を使用して、そのインターフェイスを公開するクラスの CLSID を判断します。この CLSID を使用して、ラッパー用メタデータを特定できます。
この時点でクラスを識別できない場合には、マーシャラは System.__ComObject という名前の汎用ラッパー クラスでインターフェイスをラップします。