1. 程式人生 > >ArcGIS Engine 開發 (三)COM技術中的IUnknown介面和QueryInterface(介面查詢)

ArcGIS Engine 開發 (三)COM技術中的IUnknown介面和QueryInterface(介面查詢)

IUnknown

IUnknown 介面是元件物件模型(COM)中的基礎介面。COM規格書中規定COM物件至少要實現此一介面,而且其他所有的COM介面都需要派生自IUnknown介面。 IUnknown提供所有COM物件都支援的兩種基本特性:

  • 利用引用計數來進行物件生命週期管理;(控制物件生命週期
  • 以及訪問許多事先定義的介面。(介面查詢

IUnknown介面會包括一個指向虛擬方法表(英語:virtual method table)的指標,虛擬方法表是一個有許多函式指標的列表,函式指標會指向許多實現IUnknown介面所宣告的函式,以和介面中宣告順序相同的方式排列。而程序內呼叫產生的開銷(英語:Overhead (computing))大致和C++中呼叫虛擬方法的開銷相近。

方法

物件生存期由兩個方法控制,AddRefRelease,以及內部引用計數器。每個物件都必須具有IUnknown的實現來控制其生命週期。無論何時建立或複製介面指標,都會呼叫AddRef方法,當客戶端不再需要此指標時,將呼叫相應的Release方法。當引用計數達到零時,物件會自行銷燬。 客戶端還使用IUnknown獲取物件上的其他介面。QueryInterface是客戶端在需要物件上的另一個介面時呼叫的方法。當客戶端呼叫QueryInterface時,該物件提供一個介面並呼叫AddRef。實際上,任何COM方法都有責任返回一個介面來代表呼叫者遞增物件的引用計數。當不再需要該介面時,客戶端必須呼叫Release

方法。僅當介面重複時,客戶端才會顯式呼叫AddRefIUnknown介面中有三個方法QueryInterface, AddRef, and Release

[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("00000000-0000-0000-C000-000000000046")]
public interface IUnknown
{
    [PreserveSig]
    int QueryInterface(ref Guid riid, out IntPtr ppvObject);
    [PreserveSig]
    uint AddRef();
    [PreserveSig]
    uint Release();
}
  • QueryInterface可以讓呼叫此物件的程式可以確認此物件是否支援特定的介面,若是支援,則參考到此物件在特定介面下的實現。這個方法類似C++的dynamic_cast<>或是Java或是C#的casts。此方法在給定一個對應特定介面的全域性唯一識別符號(一般也稱為介面識別符號或是IID,如AE中GUID)時,可以提供一個指定特定介面的指標。若COM物件不支援此介面,會回覆E_NOINTERFACE錯誤。
  • AddRef是在新的客戶端程式要訪問此物件時,讓計數值加一,會回傳更新後的計數值。
  • Release是在客戶端程式已結束訪問此物件,讓計數值減一,會回傳更新後的計數值,若計數值已變為零,會自動刪除此一COM物件。

IUnknown本身的介面識別符號為{00000000-0000-0000-C000-000000000046},IUnknown的三個方法都是純虛擬方法(宣告時都有加上= 0),因此無法定義IUnknown類別的物件,需要由其他類別繼承IUnknown,才能定義對應類別的物件。

QueryInterface

QueryInterface方法通常用首字母縮寫詞 QI 表示。

在開發COM物件時,開發人員必須遵守QueryInterface的規則。這些規則規定物件的介面是對稱的,可傳遞的和反身的,並且在物件的生命週期中始終可用。對於客戶端,這意味著給定物件的有效介面,通過對QueryInterface的呼叫,詢問該物件對該物件(包括其自身)的任何其他介面始終是有效的。由於時間或安全性限制,不可能支援介面並隨後拒絕訪問該介面。

QueryInterface的規則規定物件的介面是自反的,對稱的和可傳遞的。始終可以在物件上保持有效的介面指標,以獲取該物件上的任何其他介面。

當請求特定介面時,QueryInterface方法可以為該請求的介面返回已分配的記憶體塊,或者它可以分配新的記憶體並返回該記憶體。必須返回同一塊記憶體的唯一情況是請求IUnknown介面。比較兩個介面指標以檢視它們是否指向同一個物件時,重要的是不執行簡單的比較。要正確比較兩個介面指標以檢視它們是否屬於同一物件,必須同時查詢它們的IUnknown介面,並且必須對IUnknown指標執行比較。通過這種方式,IUnknown介面被稱為定義COM物件的標識。

由於IUnknown是所有COM物件的基礎,因此通常在任何ArcObjects文件和類圖中都沒有對IUnknown的引用。

在AE中介面跳轉方法

IMap pMap;
IActiveView pActiveView;
pMap = axMapControl1.Map;
...
pActiveView = pMap as IActiveView;//方法一
// pActiveView = (IActiveView) pMap;//方法二