共用方式為


執行階段可呼叫封裝

公用語言執行平台 (CLR) 會透過稱為運行階段可呼叫包裝器 (RCW) 的代理程式公開 COM 物件。 雖然 RCW 對 .NET 用戶端來說似乎是一個普通的物件,但其主要功能是封送處理 .NET 用戶端與 COM 物件之間的呼叫。

運行時間會為每個 COM 物件建立一個 RCW,而不論該物件上存在的參考數目為何。 執行階段會針對每個物件,在每個程序中維護單一的 RCW。 如果您在一個應用程式域或 Apartment 中建立 RCW,然後將參考傳遞至另一個應用程式域或 Apartment,則會使用第一個物件的 Proxy。 請注意,此 Proxy 是新的 Managed 物件,與初始 RCW 不同;這表示兩個 Managed 物件不相等,但確實代表相同的 COM 物件。 如下圖所示,任何數目的受管理的用戶端都可以保存公開 INew 介面和 INewer 介面之 COM 物件的參考。

下圖顯示透過執行時間可呼叫包裝函式存取 COM 物件的程式:

透過 RCW 存取 COM 物件的程式。

使用從類型函式庫衍生的中繼資料,執行階段會建立所呼叫的 COM 物件以及該物件的包裝函式。 每個 RCW 都會在它包裝的 COM 物件上維護介面指標的快取,並在不再需要 RCW 時,在 COM 物件上釋放其參考。 運行時間會在 RCW 上執行垃圾收集。

除了其他活動之外,RCW 會代表包裝的物件,封送處理 Managed 和 Unmanaged 程式代碼之間的數據。 具體來說,當用戶端和伺服器之間傳遞的數據表示法有差異時,RCW 會為方法參數和方法傳回值提供封送處理。

標準包裝函式會強制執行內建封送處理規則。 例如,當 .NET 用戶端將類型作為引數的一部分傳遞到非受控制的物件時,包裝函式會將 string 類型轉換為 string 類型。 如果 COM 物件傳回 BSTR 至其 Managed 呼叫端,呼叫端會收到 string。 用戶端和伺服器都會傳送和接收熟悉的數據。 其他類型不需要轉換。 例如,標準包裝函式一律會在Managed和Unmanaged程式碼之間傳遞4位元組整數,而不需要轉換類型。

封送處理選取的介面

執行階段可呼叫包裝器(RCW)的主要目標是隱藏受控和非受控程式設計模型之間的差異。 若要建立無縫轉換,RCW 會取用選取的 COM 介面,而不需將其公開至 .NET 用戶端,如下圖所示。

下圖顯示 COM 介面和執行階段可呼叫封裝器。

運行時可調用包裝器的介面螢幕截圖。

建立為早期綁定物件時,RCW 是特定類型。 它會實作 COM 物件所實作的介面,並從物件的介面公開方法、屬性和事件。 在圖例中,RCW 會公開 INew 介面,但會取用 IUnknownIDispatch 介面。 此外,RCW 會將 INew 介面的所有成員公開給 .NET 用戶端。

RCW 會使用下表所列的介面,這些介面是由其包裝的物件所公開。

介面 說明
IDispatch 要使用反射對 COM 物件進行延遲繫結。
IErrorInfo 提供錯誤的文字描述、其來源、說明檔案、說明上下文,以及定義錯誤之介面的 GUID(對 .NET 類別始終為 GUID_NULL)。
IProvideClassInfo 如果包裝的 COM 物件實作 IProvideClassInfo,RCW 會從這個介面擷取類型資訊,以提供更好的類型識別。
IUnknown 針對物件識別、型別轉換和生命週期管理:

- 對象識別
運行時間會比較每個物件的 IUnknown 介面值,以區分 COM 物件。
- 類型強制
RCW 會辨識 QueryInterface 方法所執行的動態類型探索。
- 生命週期管理
使用 QueryInterface 方法,RCW 會取得並保存 Unmanaged 對象的參考,直到運行時間對包裝函式執行垃圾收集為止,該包裝函式會釋放 Unmanaged 物件。

RCW 會選擇性地取用下表所列的介面,這些介面會由它包裝的對象公開。

介面 說明
IConnectionPointIConnectionPointContainer RCW 會將公開連接點事件樣式的物件轉換成委派型事件。
IDispatchEx (僅限.NET Framework) 如果類別實作 IDispatchEx,RCW 會實作 IExpandoIDispatchEx 介面是 IDispatch 介面的延伸模組,不同於 IDispatch,可啟用成員的列舉、新增、刪除和區分大小寫呼叫。
IEnumVARIANT 啟用支援列舉的 COM 類型,可視為集合。

另請參閱