首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# COM 互操作 (二 續):as/is 型別轉換語義變化與手工 IUnknown 介面查詢代碼

     編輯:關於C語言

C# 型別轉換兩種形式

  • (IJetEngine)engine:強制轉型,失敗拋 InvalidCastException。
  • engine as IJetEngine:安全轉型,失敗回傳 null。

應用於 COM 包裝類的語義變化


object o1 = new Demo(); // 實作 IDemo
object o2 = new Demo1(); // 未實作 IDemo
IDemo d1 = o1 as IDemo; // 成功
IDemo d2 = o2 as IDemo; // null

// COM 包裝類
IJetEngine e = new JetEngineClass() as IJetEngine; // 成功
// 即使 JetEngineClass 未在 C# 聲明實作 IJetEngine,
// 只要底層 COM 物件 QueryInterface 支援該介面即可成功。

普通類別:編譯期型別檢查決定成敗。
COM 包裝類:運行期 QueryInterface 決定成敗,as/is 變相成為「介面支援性檢測」運算子。

手工聲明 IUnknown 介面查詢


[ComImport, Guid("00000000-0000-0000-C000-000000000046")]
interface IUnknown
{
    void QueryInterface([In] ref Guid iid, [Out] out IntPtr ppvObj);
    int AddRef(); int Release();
}

[ComImport, CoClass(typeof(JetEngineClass)), Guid("9F63D980-FF25-11D1-BB6F-00C04FAE22DA")]
interface IJetEngine1 : IUnknown { /* 方法 */ }

[ComImport, CoClass(typeof(JetEngineClass)), Guid("9F63D980-FF25-11D1-BB6F-00C04FAE22DA")]
interface IJetEngine2 { /* 內含 IUnknown 三方法 */ void QueryInterface(...); int AddRef(); int Release(); /* 方法 */ }

// 使用
IJetEngine1 i1 = GetJetEngine() as IJetEngine1;
IntPtr p1; i1.QueryInterface(typeof(IUnknown).Guid, out p1);

IJetEngine2 i2 = GetJetEngine() as IJetEngine2;
IntPtr p2; i2.QueryInterface(typeof(IUnknown).Guid, out p2);

注意:IUnknown 方法必須置於介面聲明最開頭 (對應虛函數表順序)。此法雖可行,但回到指標操作,失去 RCW 便利。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved