預先定義的屬性 (MIDL 3.0)

有許多預先定義的自訂屬性,可讓您控制編譯器合成介面 (IID) 的名稱和介面識別碼。 這些屬性可讓您在更細微的層級控制類別的版本控制和二進位 API。

如果您是元件開發人員及/或程式庫作者,則您可能會想要使用這些屬性,以確保您的元件在下一個版本中維持二進位穩定的狀態。

如果您是應用程式開發人員,則通常不需要使用這些屬性,因為在修正您的類型之後,您將會重新編譯應用程式。

[allowforweb]屬性

如需屬性用法和用途 allowforweb 的詳細資訊,請參閱 AllowForWebAttribute 類別

[constructor_name]屬性

constructor_name屬性會指定包含函式成員之 factory 介面的名稱和 IID。 如需 factory 介面的詳細資訊,請參閱 合成介面

注意

處理站介面只適用于具有非預設的函式的密封類別,或使用預設和/或非預設的函式的未密封類別。

在下列範例中,受保護的 區塊 的函式會放在 IBlockFactory 介面中,而且該介面具有指定的 IID。

[constructor_name("Windows.UI.Xaml.Documents.IBlockFactory", 07110532-4f59-4f3b-9ce5-25784c430507)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    protected Block();
    ...
}

如此一來,當您的類別描述未以其他方式參考介面,但需要它來執行類別時,MIDL 3.0 編譯器就會會合成並視需要新增介面。

[contentproperty]屬性

contentproperty屬性代表ContentPropertyAttribute類別。 以下是範例:

// BgLabelControl.idl
namespace BgLabelControlApp
{
    [contentproperty("Content")]
    runtimeclass BgLabelControl : Windows.UI.Xaml.Controls.Control
    {
        BgLabelControl();
        static Windows.UI.Xaml.DependencyProperty LabelProperty{ get; };
        String Label;
        static Windows.UI.Xaml.DependencyProperty ContentProperty{ get; };
        IInspectable Content;
    }
}

[contract]屬性

請勿在您自己的 contract api 中使用屬性,它只有內建 Windows api 的意義。

contract屬性會指定 Windows 10 API 合約的名稱和版本 (請參閱使用延伸模組 sdk 進行程式設計) ,其中的屬性型別和(或)成員會先引進 Windows (,因此對於未在 Windows) 中傳遞的 api 而言並不具意義。 屬性會採用表單 [contract(ContractName, ContractVersion)] ,而且會出現在其所套用的專案之前。

[default]屬性

如果您未指定預設介面,MIDL 3.0 編譯器會選擇第一個實例介面。 若要覆寫此選項,請在您想要作為預設介面的介面之前插入 default 屬性。

// Declaring an external interface as the default
runtimeclass C : [default]I { ... }

// Declaring a specific exclusiveto interface as the default.
// This is very unusual.
runtimeclass C
{
    ...

    [default][interface_name(...)]
    {
        ...
    }
}

[default_interface]屬性

default_interface屬性是用來強制產生預設介面,而不會產生任何另一個。 在下列範例中, StateTriggerBase 不需要預設介面 (,因為它沒有) 的公用非靜態成員,所以它只是存在 default_interface 會產生一個 (名為 IStateTriggerBase) 的屬性。

[default_interface]
unsealed runtimeclass StateTriggerBase
{
    protected void SetActive(Boolean IsActive);
};

[default_overload]屬性

注意

函式不支援這個屬性。 如果您無法以 arity 來多載您的函式,則可以定義多載的 factory 方法,例如本節最後一個程式碼片段中所示的 CreateFromUriCreateFromStream 範例。

default_overload屬性代表windows.foundation.metadata.defaultoverloadattribute 裝飾類別,表示方法是預設的多載方法。 本節將逐步引導您完成屬性的 原因 和使用指導方針 [default_overload]

您可以透過arity自由多載 Windows 執行階段方法。 也就是說,您可以定義多個具有相同名稱的方法,只要每個方法都接受不同數目的引數即可。 基於可用性的考慮,建議您將新的參數加入至結尾,而且較短的參數清單函式的行為相當於使用 (案例特定的) 預設的遺漏參數的預設值來呼叫較長的參數清單函數。

runtimeclass Widget
{
    void Start();
    void Start(StartMode mode);
    void Start(StartMode mode, Widget parent);
}

在上述範例中,可以使用兩個參數來呼叫 start ,以指定啟動模式和父 widget。 如果您省略父小工具,則會預設為 null。 如果您省略模式,則會在某些案例特定的預設模式下啟動。

在下一個範例中,我們使用DeviceInformation >createwatcher。

runtimeclass DeviceInformation
{
    static DeviceWatcher CreateWatcher();
    static DeviceWatcher CreateWatcher(DeviceClass deviceClass);
    static DeviceWatcher CreateWatcher(String aqsFilter);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties,
                                       DeviceInformationKind kind);
}

在該範例中,有五個多載,其中大部分都遵循建議的模式,讓每個新的多載成為先前多載的延伸。

如果您決定有多個具有相同參數數目之方法的多載,則會收到編譯器錯誤:

DeviceInformation 的1參數多載只能以 Windows 的方式,指定為預設多載。Windows.foundation.metadata.defaultoverloadattribute 裝飾。

這是因為某些程式設計語言是以動態方式輸入的。 JavaScript 和 Python 有兩個範例。 針對這些語言,多載的選取範圍只會考慮參數的數目,而不是其類型。 這表示 JavaScript 呼叫 DeviceInformation.createWatcher(v); 不明確—應該將 v 強制轉型為 DeviceClass字串

若要解決不明確的問題,您必須將 [default_overload] 屬性套用至其中一個方法。 但是您要如何選擇哪一個呢?

您應該選擇預設多載,讓非預設多載的功能仍可透過其他方式(通常是其他多載)使用。

DeviceInformation. >createwatcher範例中,可以藉由呼叫字串iiterable < 字串 >多載,並傳遞空白的屬性清單來取得字串多載的功能。 另一方面, DeviceClass多載是建立篩選到DeviceClassDeviceWatcher的唯一方法。

這會讓 DeviceClass 方法成為明確的優勝者。 您可以藉由 [default_overload] 將屬性套用至該多載來表示。

runtimeclass DeviceInformation
{
    static DeviceWatcher CreateWatcher();
    [default_overload]
    static DeviceWatcher CreateWatcher(DeviceClass deviceClass);
    static DeviceWatcher CreateWatcher(String aqsFilter);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties);
    static DeviceWatcher CreateWatcher(String aqsFilter,
                                       IIterable<String> additionalProperties,
                                       DeviceInformationKind kind);
}

如果沒有獲勝者,因為所有衝突的多載都提供了其他多載無法使用的獨特功能?

runtimeclass Widget
{
    static Widget Create(Uri source);
    static Widget Create(IInputStream source);
}

我們的假設 Widget 物件可從 Uri建立,或從輸入資料流程建立。 如果我們將一個標記標記為預設多載,則動態類型的程式設計語言會完全無法存取另一個。

若要解決這個問題,請將兩個版本命名為不同的名稱,使其不會超載。

runtimeclass Widget
{
    static Widget CreateFromUri(Uri source);
    static Widget CreateFromStream(IInputStream source);
}

現在這兩種建立模式都適用于所有語言。

另請參閱 方法 多載和以 類別為基礎的投射

[interface_name]屬性

interface_name屬性指定包含類別實例成員之介面的名稱和 IID。 根據預設,編譯器會使用針對 方法所使用的相同唯一編號演算法來指派介面名稱。

在下列範例中,套用至 runtimeclass 的 interface_name 屬性會指定介面的名稱和 IID,此介面包含類別的所有實例成員,但這些成員未指派給介面。 因此, LineHeightLineStackingStrategyMargin>textalignmentIBlock 介面的成員。

不過, HorizontalTextAlignmentIBlock2 介面的成員,因為 interface_name 包含該成員的屬性。

[interface_name("Windows.UI.Xaml.Documents.IBlock", 4bce0016-dd47-4350-8cb0-e171600ac896)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    Double LineHeight;
    Windows.UI.Xaml.LineStackingStrategy LineStackingStrategy;
    Windows.UI.Xaml.Thickness Margin;
    Windows.UI.Xaml.TextAlignment TextAlignment;

    [interface_name("Windows.UI.Xaml.Documents.IBlock2", 5ec7bdf3-1333-4a92-8318-6caedc12ef89)]
    {
        Windows.UI.Xaml.TextAlignment HorizontalTextAlignment;
    }
    ...
}

您也可以使用 interface_name 屬性來強制產生介面。 在下列範例中, StateTriggerBase 不需要 IStateTriggerBase,而且只是存在 interface_name 造成它產生的屬性。

[interface_name("Windows.UI.Xaml.IStateTriggerBase", 48b20698-af06-466c-8052-93666dde0e49)]
unsealed runtimeclass StateTriggerBase
{
    protected void SetActive(Boolean IsActive);
};

如此一來,當您的類別描述未以其他方式參考介面,但需要它來執行類別時,MIDL 3.0 編譯器就會會合成並視需要新增介面。

如果您使用非必要的 default_interface ,MIDL 3.0 會產生額外的 空白 介面,並使其成為預設值。

[method_name]屬性

每個 Windows 執行階段介面都有對等的應用程式二進位介面 (ABI) 介面。 ABI 介面需要所有成員都有唯一的名稱。 MIDL 3.0 有兩種情況,其中的成員沒有名稱,或沒有唯一的名稱。

  • 函數和
  • 兩個以上的多載方法。

在這些情況下,MIDL 3.0 編譯器會視需要會合成唯一的成員名稱。

根據預設,編譯器會針對 ABI 介面中的相同方法,指派名稱>< 類別、 <classname> 2、 <classname> 3 等的函式方法。 換句話說,最小未使用的整數數位尾碼 (從 2) 增加,以使函式方法名稱成為唯一的。

同樣地,針對多載方法,針對一系列多載中的第一個方法 (在 [詞法順序]) 中,編譯器會針對相等的 ABI 介面方法使用原始方法名稱。 後續的多載是藉由將最小未使用的整數數位尾碼新增至原始名稱, (從 2) 增加而成為唯一的。

例如,下列 IDL 會宣告 DoWork的三個多載,以及名為 DoWork3的不同方法的兩個多載。

void DoWork(Int32 x);
void DoWork3(Int32 x);
void DoWork(Int32 x, Int32 y);
void DoWork(Int32 x, Int32 y, Int32 z);
void DoWork3(Int32 x, Int32 y);

根據預設 (由於已) 名稱 DoWork3 ,因此編譯器會提供 DoWork 名稱的三個多載

  • DoWork
  • DoWork2
  • DoWork4

DoWork3DoWork 多載。 根據預設,編譯器會提供 DoWork3 名稱的兩個多載

  • DoWork3
  • DoWork32

在 vtable 順序中,函數會顯示為

  • DoWork
  • DoWork3
  • DoWork2
  • DoWork4
  • DoWork32

您可以使用 method_name 屬性來覆寫編譯器的預設名稱指派。

在下一個範例中,我們會指示編譯器針對Block預設的函式成員使用 name CreateInstance

unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    [method_name("CreateInstance")] protected Block();
    ...
}

[static_name]屬性

static_name屬性指定包含類別之靜態成員的介面名稱和 IID。

在下一個範例中,套用至 runtimeclass 的 static_name 屬性會指定介面的名稱和 IID,而此介面包含類別的所有靜態成員,但未指派給介面。 因此, LineHeightPropertyLineStackingStrategyPropertyMarginPropertyTextAlignmentPropertyIBlockStatics 介面的成員。

不過, HorizontalTextAlignmentPropertyIBlockStatics2 介面的成員,因為 static_name 包含該成員的屬性。

[static_name("Windows.UI.Xaml.Documents.IBlockStatics", f86a8c34-8d18-4c53-aebd-91e610a5e010)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
    ...
    static Windows.UI.Xaml.DependencyProperty LineHeightProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty LineStackingStrategyProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty MarginProperty{ get; };
    static Windows.UI.Xaml.DependencyProperty TextAlignmentProperty{ get; };

    [static_name("Windows.UI.Xaml.Documents.IBlockStatics2", af01a4d6-03e3-4cee-9b02-2bfc308b27a9)]
    {
        static Windows.UI.Xaml.DependencyProperty HorizontalTextAlignmentProperty{ get; };
    }
    ...
}