Atribut yang telah ditentukan sebelumnya (MIDL 3.0)
Ada sejumlah atribut kustom yang telah ditentukan sebelumnya yang memungkinkan Anda mengontrol nama dan pengidentifikasi antarmuka (IID) untuk antarmuka yang disintesis kompilator. Atribut ini memungkinkan Anda mengontrol penerapan versi dan API biner kelas Anda pada tingkat mendetail.
Jika Anda adalah pengembang komponen dan/atau penulis pustaka, maka Anda mungkin ingin menggunakan atribut ini untuk memastikan bahwa komponen Anda tetap stabil biner dari satu versi ke versi berikutnya.
Jika Anda adalah pengembang aplikasi, maka secara umum Anda tidak perlu menggunakan atribut ini karena Anda akan mengkompilasi ulang aplikasi setelah merevisi jenis Anda.
Untuk detail tentang penggunaan dan tujuan allowforweb
atribut, lihat kelas AllowForWebAttribute.
Atribut constructor_name
menentukan nama dan IID antarmuka pabrik yang berisi anggota konstruktor. Lihat Mensintesis antarmuka untuk informasi selengkapnya tentang antarmuka pabrik.
Catatan
Antarmuka pabrik hanya berlaku untuk kelas yang disegel dengan konstruktor non-default, atau ke kelas yang tidak disegel dengan konstruktor default dan/atau non-default.
Dalam contoh di bawah ini, konstruktor Blok yang dilindungi ditempatkan di antarmuka IBlockFactory , dan antarmuka tersebut memiliki IID yang ditentukan.
[constructor_name("Windows.UI.Xaml.Documents.IBlockFactory", 07110532-4f59-4f3b-9ce5-25784c430507)]
...
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
...
protected Block();
...
}
Akibatnya, ketika deskripsi kelas Anda tidak mereferensikan antarmuka, tetapi ketika seseorang diperlukan untuk mengimplementasikan kelas , kompilator MIDL 3.0 mensintesis dan menambahkan antarmuka, seperlunya.
contentproperty
atribut mewakili kelas ContentPropertyAttribute. Berikut contohnya:
// 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;
}
}
Jangan gunakan contract
atribut di API Anda sendiri; hanya memiliki arti untuk API Windows bawaan.
Atribut contract
menentukan nama dan versi kontrak API Windows 10 (lihat Pemrograman dengan SDK ekstensi) di mana jenis dan/atau anggota yang diatribusikan pertama kali diperkenalkan ke Windows (karenanya tidak bermakna untuk API yang tidak dikirimkan sebagai bagian dari Windows). Atribut mengambil formulir [contract(ContractName, ContractVersion)]
, dan muncul sebelum item yang diterapkannya.
Jika Anda tidak menentukan antarmuka default, pengkompilasi MIDL 3.0 memilih antarmuka instans pertama. Untuk mengambil alih pilihan ini, sisipkan default
Atribut sebelum antarmuka yang Anda inginkan menjadi antarmuka 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(...)]
{
...
}
}
Atribut default_interface
ini digunakan untuk memaksa pembuatan antarmuka default di mana atribut tidak akan dihasilkan. Dalam contoh di bawah ini, StateTriggerBase tidak memerlukan antarmuka default (karena tidak memiliki anggota nonstatis publik), jadi hanya ada default_interface
atribut yang menyebabkan satu (bernama IStateTriggerBase) dihasilkan.
[default_interface]
unsealed runtimeclass StateTriggerBase
{
protected void SetActive(Boolean IsActive);
};
Catatan
Atribut ini tidak didukung untuk konstruktor. Jika Anda tidak dapat membebani konstruktor Berdasarkan aritas, maka Anda dapat menentukan metode pabrik yang kelebihan beban seperti contoh CreateFromUri dan CreateFromStream yang ditunjukkan dalam cuplikan kode terakhir di bagian ini.
Atribut default_overload
mewakili kelas DefaultOverloadAttribute , yang menunjukkan bahwa metode adalah metode kelebihan beban default. Bagian ini memancarkan Anda melalui alasan , dan pedoman penggunaan untuk, [default_overload]
atribut .
Anda dapat dengan bebas membebani metode Windows Runtime berdasarkan aritas. Artinya, Anda dapat menentukan beberapa metode dengan nama yang sama, selama masing-masing metode mengambil jumlah argumen yang berbeda. Untuk tujuan kegunaan, kami sarankan Anda menambahkan parameter baru ke akhir, dan bahwa perilaku fungsi daftar parameter yang lebih pendek setara dengan memanggil fungsi daftar parameter yang lebih panjang dengan default alami (khusus skenario) untuk parameter yang hilang.
runtimeclass Widget
{
void Start();
void Start(StartMode mode);
void Start(StartMode mode, Widget parent);
}
Dalam contoh di atas, Mulai dapat dipanggil dengan dua parameter untuk menentukan mode mulai dan widget induk. Jika Anda menghilangkan widget induk, maka defaultnya ke null. Dan jika Anda menghilangkan mode, mode dimulai dalam beberapa mode default khusus skenario.
Kami menggunakan DeviceInformation.CreateWatcher dalam contoh berikutnya.
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);
}
Dalam contoh itu ada lima kelebihan beban, dan sebagian besar dari mereka mengikuti pola yang direkomendasikan untuk memiliki setiap kelebihan beban baru menjadi ekstensi dari kelebihan beban sebelumnya.
Jika Anda memutuskan untuk memiliki beberapa kelebihan beban metode dengan jumlah parameter yang sama, maka Anda mendapatkan kesalahan kompilator:
Kelebihan 1 parameter DeviceInformation.CreateWatcher harus memiliki satu metode yang ditentukan sebagai kelebihan beban default dengan mendekorasinya dengan Windows.Foundation.Metadata.DefaultOverloadAttribute.
Alasannya adalah bahwa beberapa bahasa pemrograman dititik secara dinamis. JavaScript dan Python adalah dua contoh. Untuk bahasa ini, pemilihan kelebihan beban hanya mempertimbangkan jumlah parameter, dan bukan jenisnya. Ini berarti bahwa panggilan JavaScript ke DeviceInformation.createWatcher(v);
ambigu— haruskah v dipaksa ke DeviceClass, atau ke String?
Untuk mengatasi ambiguitas, Anda perlu menerapkan [default_overload]
atribut ke salah satu metode. Tapi bagaimana Anda memilih yang mana?
Anda harus memilih kelebihan beban default sehingga fungsionalitas kelebihan beban non-default masih tersedia dengan cara lain, biasanya oleh salah satu kelebihan beban lainnya.
Dalam contoh DeviceInformation.CreateWatcher , fungsionalitas kelebihan string dapat diperoleh dengan memanggil String, IIterable<String> overload, dan meneruskan daftar properti kosong. Di sisi lain, kelebihan Beban DeviceClass adalah satu-satunya cara untuk membuat DeviceWatcher yang difilter ke DeviceClass.
Itu membuat metode DeviceClass menjadi pemenang yang jelas. Jadi Anda menunjukkan bahwa dengan menerapkan atribut ke kelebihan beban tersebut [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);
}
Bagaimana jika tidak ada pemenang karena semua kelebihan beban yang bertentangan menyediakan fungsionalitas unik yang tidak tersedia dari kelebihan beban lainnya?
runtimeclass Widget
{
static Widget Create(Uri source);
static Widget Create(IInputStream source);
}
Objek Widget hipotetis kami dapat dibuat dari Uri, atau dibuat dari aliran input. Jika kita menandainya sebagai kelebihan beban default, maka bahasa pemrograman yang ditik secara dinamis benar-benar kehilangan akses ke yang lain.
Untuk mengatasi masalah ini, beri dua versi nama yang berbeda agar tidak kelebihan beban.
runtimeclass Widget
{
static Widget CreateFromUri(Uri source);
static Widget CreateFromStream(IInputStream source);
}
Sekarang kedua pola pembuatan tersedia untuk semua bahasa.
Lihat juga Metode kelebihan beban dan Proyeksi berbasis kelas.
Atribut interface_name
menentukan nama dan IID antarmuka yang berisi anggota instans kelas. Secara default, pengkompilasi menetapkan nama antarmuka menggunakan algoritma penomoran unik yang sama dengan yang digunakannya untuk metode.
Dalam contoh di bawah ini, interface_name
atribut yang diterapkan ke runtimeclass menentukan nama dan IID antarmuka yang berisi semua anggota instans kelas yang tidak ditetapkan ke antarmuka. Jadi, LineHeight, LineStackingStrategy, Margin, dan TextAlignment adalah anggota antarmuka IBlock .
Namun, HorizontalTextAlignment adalah anggota antarmuka IBlock2 , karena atribut yang mencakup anggota tersebut 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;
}
...
}
Anda juga dapat menggunakan interface_name
atribut untuk memaksa pembuatan antarmuka. Dalam contoh di bawah ini, StateTriggerBase tidak memerlukan IStateTriggerBase, dan hanya adanya interface_name
atribut yang menyebabkannya dihasilkan.
[interface_name("Windows.UI.Xaml.IStateTriggerBase", 48b20698-af06-466c-8052-93666dde0e49)]
unsealed runtimeclass StateTriggerBase
{
protected void SetActive(Boolean IsActive);
};
Akibatnya, ketika deskripsi kelas Anda tidak mereferensikan antarmuka, tetapi ketika seseorang diperlukan untuk mengimplementasikan kelas , kompilator MIDL 3.0 mensintesis dan menambahkan antarmuka, seperlunya.
Jika Anda menggunakan yang default_interface
tidak perlu, maka MIDL 3.0 menghasilkan antarmuka kosong ekstra, dan menjadikannya default.
Setiap antarmuka Windows Runtime memiliki antarmuka Application Binary Interface (ABI) yang setara. Antarmuka ABI mengharuskan semua anggota memiliki nama yang unik. Ada dua kasus di MIDL 3.0 di mana anggota tidak memiliki nama, atau tidak memiliki nama yang unik.
- konstruktor, dan
- dua atau lebih metode yang kelebihan beban.
Dalam kasus ini, pengkompilasi MIDL 3.0 mensintesis nama anggota yang unik, seperlunya.
Secara default, pengkompilasi menetapkan metode konstruktor nama <className>, <className>2, <className>3, dan sebagainya untuk metode yang setara di antarmuka ABI. Dengan kata lain, akhiran numeral bilangan bulat terkecil yang tidak digunakan (meningkat dari 2) ditambahkan untuk membuat nama metode konstruktor unik.
Demikian pula, untuk metode yang kelebihan beban, untuk metode pertama dalam serangkaian kelebihan beban (dalam urutan leksikal), pengkompilasi menggunakan nama metode asli untuk metode antarmuka ABI yang setara. Kelebihan beban berikutnya dibuat unik dengan menambahkan ke nama asli akhiran numeral bilangan bulat terkecil yang tidak digunakan (meningkat dari 2).
Misalnya, IDL berikut mendeklarasikan tiga kelebihan beban DoWork, dan dua kelebihan beban metode berbeda bernama 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);
Secara default (karena nama DoWork3 sudah diambil), pengkompilasi memberikan tiga kelebihan beban DoWork nama
- DoWork
- DoWork2
- DoWork4.
DoWork3bukan kelebihan beban DoWork . Secara default, pengkompilasi memberikan dua kelebihan beban DoWork3 nama
- DoWork3
- DoWork32.
Dalam urutan vtable, fungsi akan muncul sebagai
- DoWork
- DoWork3
- DoWork2
- DoWork4
- DoWork32
Anda dapat mengganti penetapan nama default kompilator menggunakan method_name
atribut .
Dalam contoh berikutnya ini, kami menginstruksikan pengkompilasi untuk menggunakan nama CreateInstance untuk anggota konstruktor default Blok.
unsealed runtimeclass Block : Windows.UI.Xaml.Documents.TextElement
{
...
[method_name("CreateInstance")] protected Block();
...
}
Atribut static_name
menentukan nama dan IID antarmuka yang berisi anggota statis kelas.
Dalam contoh berikutnya ini, static_name
atribut yang diterapkan ke runtimeclass menentukan nama dan IID antarmuka yang berisi semua anggota statis kelas yang tidak ditetapkan ke antarmuka. Jadi, LineHeightProperty, LineStackingStrategyProperty, MarginProperty, dan TextAlignmentProperty adalah anggota antarmuka IBlockStatics .
Namun, HorizontalTextAlignmentProperty adalah anggota antarmuka IBlockStatics2 , karena atribut yang mencakup anggota tersebut 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; };
}
...
}