インポート メンバの変換
更新 : 2007 年 11 月
このトピックでは、インポート プロセスが次のメンバをどのように変換するかを説明します。
メソッド
プロパティ
イベント
Tlbimp.exe は、DispID が 0 のメソッドまたはプロパティに DefaultMemberAttribute を適用します。C# の開発者は、これらのメンバを配列として扱う必要があることに注意してください。詳しい情報については、使用しているプログラミング言語のドキュメントを参照してください。
メソッド
COM 相互運用機能は、COM の型をインポートするときに、元の COM のメソッド シグネチャと同等の .NET Framework のメソッド シグネチャを生成します。変換プロセス中、COM のパラメータ、戻り値、および HRESULT は、次の図に示すように、.NET Framework のメソッド シグネチャのパラメータ、戻り値、および HRESULT に割り当てられます。
メソッド シグネチャの変換
他の .NET クラスの場合と同様に、オブジェクト ビューアを使用するか、またはリフレクションを使用することにより、メソッドの構文を確認できます。ランタイムは、既定では、COM のオブジェクトがエラー HRESULT を返したときに対応する例外をスローします。
プロパティ
COM の開発者はプロパティやメソッドをインターフェイス上に宣言できます。すべてのプロパティは、プロパティ値を設定または取得するための、対応するアクセサ メソッドを持っています。プロパティを持つインターフェイスのタイプ ライブラリ記述をメタデータに変換するとき、インポート プロセスは、プロパティと、そのプロパティに対応する 1 つ以上のアクセサ メソッドを作成します。
タイプ ライブラリ変換プロセスは、プロパティ アクセッサ メソッドを次の方法で変換します。
[propget] 属性を持つプロパティは、同じ型のマネージ プロパティに変換され、get_propertyname と呼ばれる対応するメソッドを割り当てられます。
[propput] 属性または [propputref] 属性を持つプロパティは、同じ型のマネージ プロパティに変換され、set_propertyname と呼ばれる対応するメソッドを割り当てられます。
[propput] 属性と [propputref] 属性の両方を持つプロパティは、次のように変換されます。
[propputref] 属性と同じ型のマネージ プロパティに変換され、set_propertyname と呼ばれる対応するメソッドを割り当てられます。
[propput] 属性と同じ型の別のアクセッサ メソッドに変換され、let_propertyname という名前が与えられます。
次のタイプ ライブラリは、元のプロパティを示しています。
タイプ ライブラリ表現
interface ISample : IDispatch {
[propget] HRESULT prop1([out, retval] short *pVal);
[propput] HRESULT prop1([in] short newVal);
[propget] HRESULT prop2([out, retval] INew **pVal);
[propputref] HRESULT prop2([in] INew *newVal);
[propget] HRESULT prop3([out, retval] INew **ppINew);
[propput] HRESULT prop3([in] BSTR text);
[propputref] HRESULT prop3([in] INew *pINew);
}
変換後のプロパティは、次の Visual Basic 2005 コード片にあります。
Public Property
Get Prop1() As Integer … End Get
Set Prop1(val as Integer) … End Set
End Property
Public Property
Get Prop2() As INew … End Get
Set Prop2(val as INew) … End Set
End Property
Public Property
Get Prop3() As INew … End Get
Set Prop3(val as INew) … End Set
End Property
Public let_prop3(String as Text)
イベント
COM のタイプ ライブラリには、イベントのためのインターフェイスを定義できます。ライブラリ内の、イベントを供給するコクラスは、[source] 属性を指定することによってイベント インターフェイスを識別できます。イベント シンクがインターフェイスを実装し、イベント ソースがそのインターフェイスを使用します。COM のコネクション ポイント インターフェイス (タイプ ライブラリには記述されません) が、イベント シンクをイベント ソースに接続します。
Button クラスが IButton インターフェイスを実装し、IButtonEvents インターフェイスにイベントを供給する IDL のコード例を次に示します。
interface IButton {
HRESULT Init();
}
interface IButtonEvents {
HRESULT Click([in] int x, [in] int y);
HRESULT Resize([out, retval] int *pRetval};
}
coclass Button {
[default] interface IButton;
[default, source] interface IButtonEvents;
}
.NET のイベント モデルは、COM のコネクション ポイント モデルとは大きく異なります。イベントをシンクするマネージ クラスは、COM のコネクション ポイントを使用せずに、イベント ソースにデリゲートを渡すことによってイベントをシンクします。COM 相互運用サービスが、この 2 つの異なるイベント モデルの橋渡しをします。
インポート時に、Tlbimp.exe は、.NET イベント モデルを使用して、マネージ アプリケーションがアンマネージ クラスによって供給されるイベントをシンクできるようにするいくつかの型を作成します。Tlbimp.exe は、前の例で示した Button クラスに対応するクラスとインターフェイスを次の手順で生成します。
インポート プロセスが、イベント インターフェイスのイベントごとにデリゲート型を作成します。デリゲート名は、イベント シンク インターフェイス、アンダースコア (_)、イベント名、および EventHandler という語で構成されます。たとえば、前の例で示したタイプ ライブラリでは、Click イベントは IButtonEvents_ClickEventHandler デリゲートになります。
' A delegate for each event. Delegate Sub IButtonEvents_ClickEventHandler(ByVal x As Integer, _ ByVal y As Integer) Delegate Function IButtonEvents_ResizeEventHandler() As Integer
// A delegate for each event. delegate void IButtonEvents_ClickEventHandler(int x, int y); delegate int IButtonEvents_ResizeEventHandler();
デリゲートのシグネチャがアンマネージ メソッド シグネチャを直接変換したものであることに注意してください。
Tlbimp.exe が、既定のインターフェイスを通常の方法でインポートし、同じインターフェイス名を維持します。この例では、インターフェイスの名前は IButton です。
' Direct import of original default interface. Public Interface IButton Sub Init() End Interface
// Direct import of original default interface. public interface IButton { void Init(); }
Tlbimp.exe が、イベント インターフェイスを通常の方法でインポートし、同じインターフェイス名を維持します。この例では、インターフェイスの名前は IButtonEvent です。
' Direct import of original event interface. ' Not of interest to managed sinks. Public Interface IButtonEvents Sub Click(ByVal x As Integer, ByVal y As Integer) Function Resize() As Integer End Interface
// Direct import of original event interface. // Not of interest to managed sinks. public interface IButtonEvents { void Click(int x, int y); int Resize(); }
Tlbimp.exe は、元のインターフェイス名にサフィックス "_Event" を追加した名前を持つ第 2 のイベント インターフェイスを作成します。この第 2 のイベント インターフェイスは、メンバとして Click イベントと Resize イベントを含みます。また、イベント デリゲートのための add メソッドと remove メソッドも含んでいます。この例では、インターフェイスの名前は IButtonEvents_Event です。
' Modified version of the event interface with events ' for managed sinks.
Public Interface IButtonEvents_Event Sub Click As IButtonEvents_Click Function Resize() As IButtonEvents_Resize Sub add_Click(ByVal Click As IButtonEvents_ClickEventHandler) Sub remove_Click(ByVal Click As _ IButtonEvents_ClickEventHandler) Sub add_Resize(ByVal Resize As _ IButtonEvents_ResizeEventHandler) Sub remove_Resize(ByVal Resize As _ IButtonEvents_ResizeEventHandler) End Interface // Modified version of the event interface with events // for managed sinks. public interface IButtonEvents_Event { IButtonEvents_Click Click; IButtonEvents_Resize Resize; void add_Click(IButtonEvents_ClickEventHandler ); void remove_Click(IButtonEvents_ClickEventHandler ); void add_Resize(IButtonEvents_ResizeEventHandler ); void remove_Resize(IButtonEvents_ResizeEventHandler ); }
メモ : まれに、イベント インターフェイスにキャストする必要があることもありますが、そのような場合には、元のインターフェイスではなく Tlbimp.exe によって生成されたインターフェイスにキャストします。たとえば、IButtonEvents ではなく IButtonEvents_Event にキャストする必要があります。
Tlbimp.exe はイベントを供給するコクラスをインポートして明示的に実装されたすべてのインターフェイスが含まれるようにし、元のクラス名に Class を追加します。たとえば、Button コクラスは ButtonClass となります。また、Tlbimp.exe は、コクラスと同じ名前で、_Event サフィックスを持つ、イベント インターフェイスを実装するコクラス インターフェイスを生成します。
' This is the imported coclass interface. ' Note the underscore in IButtonEvents_Event. Public Interface Button Inherits IButton Inherits IButtonEvents_Event End Interface Public Class ButtonClass Implements Button Implements IButton Implements IButtonEvents_Event Sub Init() End Sub 'Init End Class
// This is the imported coclass interface. // Note the underscore in IButtonEvents_Event. public interface Button:IButton, IButtonEvents_Event {} public class ButtonClass:Button,IButton,IButtonEvents_Event { void Init(){} }