クラス インターフェイスの概要
更新 : 2007 年 11 月
クラス インターフェイスは、マネージ コードには明示的に定義されないインターフェイスであり、.NET オブジェクトに明示的に公開されるすべてのパブリック メソッド、プロパティ、フィールド、およびイベントを公開します。クラス インターフェイスは、デュアル インターフェイスまたはディスパッチ専用インターフェイスです。クラス インターフェイスは、.NET クラスの名前を受け取り、名前の前にアンダースコア (_) を付けます。たとえば、クラス Mammal の場合、クラス インターフェイスは _Mammal です。
派生クラスの場合、クラス インターフェイスは、基本クラスのすべてのパブリック メソッド、プロパティ、およびフィールドも公開します。派生クラスも、各基本クラスに対して、クラス インターフェイスを公開します。たとえば、クラス Mammal が、クラス MammalSuperclass を拡張し、MammalSuperclass が System.Object を拡張した場合、.NET オブジェクトは、COM クライアントに、_Mammal、_MammalSuperclass、および _Object という 3 つのクラス インターフェイスを公開します。
一例として、次の .NET クラスを考察します。
' Applies the ClassInterfaceAttribute to set the interface to dual.
<ClassInterface(ClassInterfaceType.AutoDual)> _
' Implicitly extends System.Object.
Public Class Mammal
Sub Eat()
Sub Breathe()
Sub Sleep()
End Class
// Applies the ClassInterfaceAttribute to set the interface to dual.
[ClassInterface(ClassInterfaceType.AutoDual)]
// Implicitly extends System.Object.
public class Mammal
{
void Eat();
void Breathe():
void Sleep();
}
COM クライアントは、タイプ ライブラリに記述されている _Mammal というクラス インターフェイスへのポインタを取得できます。タイプ ライブラリは、タイプ ライブラリ エクスポータ (Tlbexp.exe) ツールによって生成されます。クラス Mammal が 1 つ以上のインターフェイスを実装している場合、それらのインターフェイスは、コクラスの下に表示されます。
[odl, uuid(…), hidden, dual, nonextensible, oleautomation]
interface _Mammal : IDispatch
{
[id(0x00000000), propget] HRESULT ToString([out, retval] BSTR*
pRetVal);
[id(0x60020001)] HRESULT Equals([in] VARIANT obj, [out, retval]
VARIANT_BOOL* pRetVal);
[id(0x60020002)] HRESULT GetHashCode([out, retval] short* pRetVal);
[id(0x60020003)] HRESULT GetType([out, retval] _Type** pRetVal);
[id(0x6002000d)] HRESULT Eat();
[id(0x6002000e)] HRESULT Breathe();
[id(0x6002000f)] HRESULT Sleep();
}
[uuid(…)]
coclass Mammal
{
[default] interface _Mammal;
}
クラス インターフェイスの生成は、省略できます。既定では、COM 相互運用機能により、タイプ ライブラリにエクスポートされるクラスごとに 1 つのディスパッチ専用インターフェイスが生成されます。クラスに ClassInterfaceAttribute を適用することにより、このクラス インターフェイスを自動生成しないようにするか、または自動生成の方法を変更できます。クラス インターフェイスによって、COM へのマネージ クラス公開の作業は簡単になりますが、その使用には制限があります。
注意 : |
---|
独自に明示的に定義する代わりに、クラス インターフェイスを使用した場合、将来のマネージ クラスのバージョン管理が複雑になる可能性があります。クラス インターフェイスを使用する前に、次のガイドラインを一読してください。 |
COM クライアントが使用するインターフェイスは、クラス インターフェイスを生成するのではなく、明示的なインターフェイスを定義してください。
COM 相互運用機能はクラス インターフェイスを自動的に生成するので、クラスに対するバージョン変更後に、共通言語ランタイムによって公開されたクラス インターフェイスのレイアウトが変更される可能性があります。COM のクライアントは、通常、インターフェイスのレイアウトの変更処理に対応していないので、クラスのメンバ レイアウトを変更した場合、COM クライアントが機能しなくなります。
このガイドラインは、COM クライアントに公開されるインターフェイスは、変更不可のままにする必要があるという概念を再確認するものです。インターフェイス レイアウトを不用意に変更し、COM クライアントが機能しなくなるような危険を避けるには、インターフェイスを明示的に定義して、クラスに対する変更をインターフェイス レイアウトから切り離してください。
次のコードに示すように、ClassInterfaceAttribute を使用してクラス インターフェイスの自動生成を解除し、そのクラスに対して明示的なインターフェイスを実装します。
<ClassInterface(ClassInterfaceType.None)>Public Class LoanApp
Implements IExplicit
Sub M() Implements IExplicit.M
…
End Class
[ClassInterface(ClassInterfaceType.None)]
public class LoanApp : IExplicit {
void M();
}
ClassInterfaceType.None 値は、クラスのメタデータがタイプ ライブラリにエクスポートされるときに、クラス インターフェイスが生成されないようにします。上の例では、COM クライアントは、IExplicit インターフェイスを使用した場合にだけ、LoanApp クラスにアクセスできます。
ディスパッチ ID (DispId) をキャッシュしないでください。
クラス インターフェイスの使用は、スクリプト クライアント、Microsoft Visual Basic 6.0 のクライアント、またはインターフェイス メンバの DispId をキャッシュしない遅延バインディングされるクライアントに対して有効なオプションです。DispId は、遅延バインディングを可能にするためにインターフェイス メンバを識別します。
クラス インターフェイスでは、DispId はインターフェイス内のメンバの位置に基づいて生成されます。メンバの順序を変更し、そのクラスをタイプ ライブラリにエクスポートすると、クラス インターフェイス内に生成された DispId が変更される場合があります。
クラス インターフェイスを使用するときは、遅延バインディングされる COM クライアントが機能しなくなるのを防ぐために、ClassInterfaceType.AutoDispatch 値の ClassInterfaceAttribute を適用してください。この値は、ディスパッチ専用クラス インターフェイスを実装しますが、タイプ ライブラリからのインターフェイス記述は省略します。インターフェイス記述がないと、クライアントはコンパイル時に DispId をキャッシュできません。ディスパッチ専用クラス インターフェイスはクラス インターフェイスの既定のインターフェイス型ですが、明示的に ClassInterfaceType.AutoDispatch 属性値を適用できます。
<ClassInterface(ClassInterfaceType.AutoDispatch)> Public Class LoanApp
Implements IAnother
Sub M() Implements IAnother.M
…
End Class
[ClassInterface(ClassInterfaceType.AutoDispatch]
public class LoanApp : IAnother {
void M();
}
インターフェイス メンバの DISPID を実行時に取得するために、COM クライアントは IDispatch.GetIdsOfNames を呼び出すことができます。インターフェイスでメソッドを呼び出すには、返された DISPID を引数として IDispatch.Invoke に渡します。
クラス インターフェイスに対して、デュアル インターフェイス オプションを使用しないでください。
デュアル インターフェイスは、COM クライアントによるインターフェイス メンバへの事前バインディングおよび遅延バインディングを可能にします。デザイン時およびテスト中は、クラス インターフェイスをデュアルに設定すると便利です。変更されることのないマネージ クラス (およびその基本クラス) も、このオプションを使用できます。それ以外の場合は、クラス インターフェイスをデュアルに設定しないでください。
自動的に生成されるデュアル インターフェイスの使用が適切なのはまれであり、ほとんどの場合、バージョン管理が複雑になります。たとえば、派生クラスのクラス インターフェイスを使用する COM のクライアントは、基本クラスの変更によって簡単に機能しなくなる可能性があります。サードパーティの基本クラスを使用したときは、クラス インターフェイスのレイアウトは制御できません。また、ディスパッチ専用インターフェイスとは異なり、デュアル インターフェイス (ClassInterface.AutoDual) は、エクスポートされたタイプ ライブラリ内にクラス インターフェイスの記述を提供します。このような記述は、遅延バインディングされるクライアントが実行時に DispId をキャッシュする結果になります。