共用方式為


匯入的型別轉換

這個主題將說明匯入處理序如何轉換下列型別:

  • 介面

  • 類別

  • 結構

  • 列舉型別

  • 常數

  • Typedef

一般而言,Tlbimp.exe 會以型別在原來型別程式庫中的同樣名稱匯入它們。 型別程式庫內的名稱必須是唯一的,這樣才可以消除轉換處理期間的命名衝突。 所有有效的型別程式庫名稱都是有效的組件名稱。

匯入的型別是以它所屬的命名空間 (與原來的型別程式庫相同) 為範圍。 這些型別是由它們的完整命名空間和型別名稱來個別地識別。

您可以使用型別程式庫中的型別程式庫屬性,來明確地控制匯入型別的 Managed 名稱。 這個使用者定義屬性識別項為 0F21F359-AB84-41e8-9A78-36D110E6D2F9。 以下型別程式庫展示了使用者定義屬性的加入。

型別程式庫表示

[  uuid(…),
    version(1.0)
]
library AcmeLib {
    interface Widget {};
    [custom(0F21F359-AB84-41e8-9A78-36D110E6D2F9, 
     "Acme.WidgetLib.Slingshot")]
    coclass Slingshot {};
};

雖然 Tlbimp.exe 是將型別程式庫匯入至 AcmeLib 命名空間,但是 Slingshot 類別卻會成為 Acme.WidgetLib.Slingshot。

介面

當匯入處理轉換介面時,會去除所有 IUnknownIDispatch 方法。 除非介面為雙重介面 (衍生自 IDispatch 的介面),否則這項轉換會將 GuidAttribute 套用至介面,以保留在型別程式庫中指派的介面識別項 (IID) 和 InterfaceTypeAttribute

型別程式庫表示

[uuid(…), ]
interface IWidget : IUnknown {
    HRESULT New()
    HRESULT Start()
};
[uuid(…), ]
interface IGadget : IWidget {
    HRESULT Baz()
};

在轉換期間,匯入處理序會將基底介面的方法加入到衍生介面。 在下列範例中,會將 New 和 Start 加入至 IGadget 介面:

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IWidget
    Sub [New]()
    Sub Start()
End Interface

<Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IGadget
    Inherits IWidget
    Shadows Sub [New]()
    Shadows Sub Start()
    Sub Baz()
End Interface
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IWidget {
    void New();
    void Start();
};
[Guid(…), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IGadget : IWidget {
    new void New();
    new void Start();
    void Baz();
};

類別

匯入處理序會建立 Managed 類別來代表每一個 COM Coclass,賦予 Managed 類別與附加在 Class 上之原始 Coclass 相同的名稱。 例如,NewNewer Coclass 會變成 NewNewerClass。 這項轉換會將 GuidAttribute 加入到類別,以擷取 Coclass 的類別識別項 (CLSID)。

除了 Managed 類別以外,匯入處理序會加入名稱與 Coclass 相同的介面,並套用 CoClassAttribute 來辨識原始 Coclass 的 CLSID。 這個介面的 IID 與 Coclass 的預設介面相同。 有了這個介面,用戶端便可永遠註冊為事件接收。

與 COM Coclass 的不同之處在於,Managed 類別可以包含類別成員。 為了與 .NET Framework 方法一致,這項轉換會將 Coclass 實作之每一介面的關聯成員加入到每一個類別。 Managed 類別的使用者可以叫用 Managed 型別的方法和屬性,而不用先轉型 (Casting) 成特定的介面。 匯入處理序也會將預設的建構函式加入到每一個轉換的 Coclass。 建構函式可以讓您從 Managed 程式碼建立類別 (無法建立沒有建構函式的類別)。 這個預設建構函式沒有引數;它的實作會呼叫基底類別建構函式。 如果將 noncreatable 型別程式庫屬性套用至 Coclass,匯入處理序將不建立這個類別的預設建構函式。

由於介面成員名稱不一定是唯一的,所以成員之間可能會發生名稱和 DispId 抵觸。 TlbImp.exe 是解決名稱抵觸的方式,是在每個抵觸的類別成員名稱前面加上介面名稱和底線。 當成員名稱抵觸時,Coclass 陳述式 (Statement) 中所列第一個介面會保持不變。

發生 DispId 抵觸時,匯入處理序會指派 DispId 給 Coclass 預設介面的成員,但不會指派給衝突的類別成員。 不過,匯入處理序永遠會指派 DispId 給介面的成員。

型別程式庫表示

[uuid(…)]
interface INew : IDispatch {
    [id(0x100)] HRESULT DoFirst();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
interface INewer : IDispatch {
    [id(0x100)] HRESULT DoNow();
    [id(0x101)] HRESULT DoSecond();
}
[uuid(…)]
coclass NewNewer  {
    [default] interface INew;
    interface INewer;
}

轉換後的型別顯示如下:

<Guid(…)> Public Interface INew
    …
End Interface

<Guid(…)> Public Interface INewer
    …
End Interface

<Guid(…)> Public Interface NewNewer
Inherits INew
    …
End Interface

<Guid(…)> Public Class NewNewerClass
Implements INew   
Implements INewer
Implements NewNewer
' Method implementation
     <DispId(100)> _
      …
End Class  
[Guid(…)]
public interface INew {…}

[Guid(…)]
public interface INewer {…}

[Guid(…)]
public interface NewNewer : INew {…}

[Guid(…)]
public class NewNewer : INew, INewer, NewNewer{
// Method implementation.
     [DispId(100)]…
}

結構

在型別程式庫內定義的結構是匯入做為中繼資料。 如果結構的某一個欄位是個參考型別,Tlbimp.exe 會將這個型別匯入為 IntPtr 並且套用 ComConversionLossAttribute。 這個屬性表示資訊在匯入過程中已遺失。

列舉型別

型別程式庫匯入工具 (Tlbimp.exe)會匯入 Unmanaged 列舉型別,當做 Managed Enum 型別。

常數

在這個版本中,常數不會從型別程式庫匯入。

Typedef

型別程式庫中的型別定義 (Typedef) 不會匯入。 而是將參數和欄位匯入做為基礎型別。 例如,BUTTON_COLOR 型別的參數會匯入為整數型別,因為 BUTTON_COLOR 是某一個整數的別名 (Alias)。

匯入之後,這些參數和欄位會含有可將它們與 ComAliasNameAttribute 中它們原來型別關聯的資訊。 轉換處理序會套用 ComAliasNameAttribute,將欄位、參數或傳回值與用作別名之程式庫中的型別程式庫名稱和型別關聯。

以下型別程式庫表示顯示 cl 參數是以 BUTTON_COLOR 做為型別,它是某一個整數的別名。

型別程式庫表示

library MyLib {
    typedef [public] int BUTTON_COLOR;

    interface ISee {
        HResult SetColor([in] BUTTON_COLOR cl);
        HResult GetColor([out, retval] BUTTON_COLOR *cl);
    };
   
    coclass See {
        [default] interface ISee
    };
};

轉換後的型別顯示如下:

public interface ISee {
    void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

public class See {
    public void SetColor([ComAliasName("MyLib.BUTTON_COLOR")]] int cl);
    [return: ComAliasName("MyLib.BUTTON_COLOR")] int GetColor();
};

請注意,BUTTON_COLOR 的實際型別在產生的中繼資料中未定義。 反之,在型別程式庫中型別設定為 BUTTON_COLOR 的參數,現在型別設定為基礎型別 int,並賦予屬性 ComAliasNameAttribute。 這個轉換處理序也會將該屬性套用至類別方法上的引數。

請參閱

概念

匯入的程式庫轉換

匯入的模組轉換

匯入的成員轉換

匯入的參數轉換

其他資源

型別程式庫至組件轉換的摘要