相互運用インターフェイスを適切に宣言する方法の明確化
質問
これは、COMインポート用のコードの書き方に関する質問です。
相互運用性インターフェイスの正しい実装に関する私の理解は、主な基準は次のとおりであるということです。
- すべてのメソッドシグネチャは互換性のある方法で一致する必要があります
- メソッドは、アンマネージインターフェイスとまったく同じ順序で.Netインターフェイスに表示される必要があります
- アンマネージインターフェイスが別のアンマネージインターフェイスを継承する場合、マネージ実装では、最初にベースレベルのインターフェイスから始めてベースレベルのインターフェイスメンバーを宣言する必要があります。
私の質問は;メンバーを表示する順序に関して、インポートするインターフェイスが別のインターフェイスから継承され、ベースインターフェイスの1つ以上のメンバーをオーバーライド/非表示にする場合、どうすればよいですか?インターフェイスメンバの宣言はどこに行くのですか?まず、ベースインターフェイスが宣言した場所または、元の位置から削除され、派生インターフェースが宣言する場所に配置されましたか?
[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)]
interface BaseComInterface
{
void method1();
void method2();
void method3();
}
[uuid(fab51c92-95c3-4468-b317-7de4d7588254)]
interface DerivedComInterface : BaseComInterface
{
void method1();
void method4();
void method5();
}
C#コードの説明:
[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
void method1(); // do I remove this one?
void method2();
void method3();
void method1(); // or this one?
void method4();
void method5();
}
解決
実際にこれを行う人の例はありますか? COMでは、インターフェイスと派生した別のインターフェイスのメソッドに同じ名前を付けることは完全に合法ですが、ほとんどすべての開発環境で派生インターフェイスを使用することは困難または不可能になります。これには、インターフェイスに基づいたCOMオブジェクトの実装と呼び出しが含まれます。
COMインターフェースでオーバーライドまたは非表示にすることはありません。 COMインターフェイスは、オブジェクトのバイナリインターフェイスをメモリに配置するための単なる契約です。インターフェイス定義のメソッドの名前は、ツールを除いて無意味です。あなたの場合、BaseComInterfaceは6つのメソッドを持つ「vtable」を約束します。最初の3つはIUnknownメソッドのシグネチャに一致し、次の3つは指定した3つのメソッドのシグネチャにすべて正しい順序で一致します。一方、DerivedComInterfaceは、9つのメソッドを含む「vtable」を約束します。最初の3つの署名はIUnknownメソッドに一致し、次の3つはBaseComInterfaceメソッドの署名に一致し、最後の3つはDerivedComInterfaceに固有の3つのメソッドに一致します。これらのメソッドの名前は、IDE、ツール、および「vtable」ポインタを見つけるために名前を必要とするコンパイラを除いて重要ではありません。
したがって、基本的に、C#、C、C ++、および他のいくつかの言語では、DerivedComInterfaceを実装するために、メソッド名の1つを修飾して「vtable」スロットを他と区別する必要があります。
質問に答えるには、どちらのメソッドもCOM契約を満たすために両方に存在する必要があるため、どちらのメソッドも削除しません。
[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
void method1();
void method2();
void method3();
void method1_2(); //Decorated to distinguish from base interface method.
void method4();
void method5();
}
これは、これらのインターフェイスがIUnknownではなくIDispatchから派生した場合に起こることを無視します。また、idlで実際にメソッドがvoidを返すように定義されている場合は、PreserveSig属性を使用してC#メソッドを修飾する必要があることに注意してください。
他のヒント
明示的なインターフェースメンバーの実装を使用することをお勧めします競合を避けるため。