如何手動建立包裝器

Note

此指引針對 .NET 框架專屬。 對於現代 .NET COM Interop,請使用原始碼產生的 COM Interop 或 System.Runtime.InteropServices.ComWrappers API。 欲了解更多資訊,請參閱 COM 互操作概述 及 COM 來源產生。

如果你決定在受管理的原始碼中手動宣告 COM 型別,最好的起點是使用現有的介面定義語言(IDL)檔案或型別函式庫。 當你沒有 IDL 檔案或無法產生型別庫檔案時,可以透過建立受管理宣告並匯出產生的組合語言到型別庫來模擬 COM 型別。

從受管理的原始碼模擬 COM 類型

  1. 在符合通用語言規範(CLS)的語言中宣告型別,並編譯該檔案。

  2. 使用 Type Library Exporter (Tlbexp.exe) 匯出包含這些型別的組件。

  3. 以匯出的 COM 型態函式庫作為宣告 COM 導向管理型別的基礎。

建立一個執行時可呼叫包裝器(RCW)

  1. 假設你有 IDL 檔案或型庫檔案,請決定你想在自訂 RCW 中包含哪些類別和介面。 你可以排除任何你不打算直接或間接用於申請的類型。

  2. 建立一個符合 CLS 標準的原始碼檔案並宣告型別。 完整匯入轉換流程說明請參閱 「類型庫轉組譯摘要 」。 實際上,當你建立自訂 RCW 時,你是在手動執行 類型庫匯入器(Tlbimp.exe)所提供的型別轉換活動。 下一節的範例展示了 IDL 或 type library 檔案中的型別,以及 C# 程式碼中對應的型別。

  3. 宣告完成後,像編譯其他受管理原始碼一樣編譯該檔案。

  4. 與 Tlbimp.exe匯入的類型一樣,有些類型需要額外資訊,你可以直接加入程式碼。 詳情請參見「如何編輯互操作組裝」。

Example

以下程式碼展示了 IDL 中介面 ISATest 與 SATest 類別的範例,以及 C# 原始碼中對應的類型。

IDL 或型別函式庫檔案

 [
object,
uuid(40A8C65D-2448-447A-B786-64682CBEF133),
dual,
helpstring("ISATest Interface"),
pointer_default(unique)
 ]
interface ISATest : IDispatch
 {
[id(1), helpstring("method InSArray")]
HRESULT InSArray([in] SAFEARRAY(int) *ppsa, [out,retval] int *pSum);
 };
 [
uuid(116CCA1E-7E39-4515-9849-90790DA6431E),
helpstring("SATest Class")
 ]
coclass SATest
 {
  [default] interface ISATest;
 };

受控原始碼中的包裝器

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

[assembly:Guid("E4A992B8-6F5C-442C-96E7-C4778924C753")]
[assembly:ImportedFromTypeLib("SAServerLib")]
namespace SAServer
{
 [ComImport]
 [Guid("40A8C65D-2448-447A-B786-64682CBEF133")]
 [TypeLibType(TypeLibTypeFlags.FLicensed)]
 public interface ISATest
 {
  [DispId(1)]
  //[MethodImpl(MethodImplOptions.InternalCall,
  // MethodCodeType=MethodCodeType.Runtime)]
  int InSArray( [MarshalAs(UnmanagedType.SafeArray,
      SafeArraySubType=VarEnum.VT_I4)] ref int[] param );
 }
 [ComImport]
 [Guid("116CCA1E-7E39-4515-9849-90790DA6431E")]
 [ClassInterface(ClassInterfaceType.None)]
 [TypeLibType(TypeLibTypeFlags.FCanCreate)]
 public class SATest : ISATest
 {
  [DispId(1)]
  [MethodImpl(MethodImplOptions.InternalCall,
  MethodCodeType=MethodCodeType.Runtime)]
  extern int ISATest.InSArray( [MarshalAs(UnmanagedType.SafeArray,
  SafeArraySubType=VarEnum.VT_I4)] ref int[] param );
 }
}

另請參閱