Система типов в среде выполнения Windows (WinRT)
Общие примечания
Все типы, кроме фундаментальных типов, должны содержаться в пространстве имен. Недопустимо, чтобы тип был в глобальном пространстве имен.
Типы, предоставляемые Windows, содержатся в пространстве имен Windows.*. Типы WinRT, не предоставляемые Windows (включая типы WinRT, предоставляемые другими частями Майкрософт), должны находиться в пространстве имен, отличном от Windows.*.
За исключением интерфейсов, все типы WinRT должны иметь общедоступную видимость. Интерфейсы WinRT могут дополнительно иметь частную видимость. Все остальные определяемые пользователем типы WinRT (структуры, классы, перечисления, делегаты, атрибуты) должны иметь общедоступную видимость.
WinRT не поддерживает вложенные типы. Ни один тип WinRT не может заключать другой тип; Тип WinRT не может быть вложен в другой тип.
Не все аспекты системы типов WinRT доступны вам в качестве стороннего разработчика.
WinRT поддерживает параметризацию интерфейсов и делегатов. Однако в этом выпуске WinRT не поддерживает определение параметризованных типов сторонними сторонами. Поддерживаются только параметризованные типы, включенные в систему в пространстве имен Windows.*.
WinRT поддерживает композицию классов в качестве механизма наследования среды выполнения. Однако в этом выпуске WinRT не поддерживает определение корневого компонуемого класса. Поддерживаются только корневые составные классы, включенные в систему в пространстве имен Windows.*.
Пространства имен и имена типов WinRT сохраняют регистр, но не учитываются, аналогичные Windows файловой системе и реестру Windows. Это означает, что у вас нет пространств имен или имен типов, которые зависят только от регистра. Например, вы не можете использовать foo.SomeType и foo. AnotherType, также не может иметь foo.SomeType и Foo.someType.
Идентификатор WinRT должен соответствовать следующей грамматике. Обратите внимание, что поддерживаются только символы, определенные в Юникоде 3.0 и более ранних версиях.
identifier-or-keyword:
identifier-start-character identifier-continuation-characters*
identifier-start-character:
letter-character
underscore (U+005F)
identifier-continuation-characters:
identifier-continuation-character
identifier-continuation-characters identifier-continuation-character
identifier-continuation-character:
identifier-start-character
decimal-digit-character
connecting-character
combining-character
formatting-character
letter-character:
A Unicode 3.0 character of classes Lu, Ll, Lt, Lm, Lo, or Nl
combining-character:
A Unicode 3.0 character of classes Mn or Mc
decimal-digit-character:
A Unicode 3.0 character of the class Nd
connecting-character:
A Unicode 3.0 character of the class Pc
formatting-character:
Zero Width Non-Joiner (U+200C)
Zero Width Joiner (U+200D)
Параметризованный тип
WinRT поддерживает параметризацию типов интерфейсов и делегатов. Параметризованные типы позволяют определить семейство интерфейсов, которые могут обрабатываться полиморфно на языках программирования, поддерживающих параметрический полиморфизм.
Экземпляр параметризованного типа возникает при указании параметризованного типа со списком аргументов типов в контексте типа, например положение параметра метода. Например, HRESULT foo(X<Y> x)
создает экземпляр параметризованного типа с именем X с типом Y в качестве первого и единственного аргумента типа.
Непараметризованный интерфейс Или делегат WinRT назначается GUID для уникальной идентификации базового интерфейса, отличающегося от других интерфейсов в том же объекте. Параметризованный интерфейс (например, IVector<T>
) или делегат (например, EventHandler<T>
) вместо этого назначается параметризованный идентификатор интерфейса (PIID), который является уникальным идентификатором GUID, идентифицируя этот параметризованный тип. Это не IID. Этот GUID используется при создании идентификаторов IID для экземпляров параметризованных типов (например, IVector<int>
).
Список аргументов параметризованного типа
Эти типы WinRT могут отображаться в списке аргументов для параметризованного типа.
- Базовые типы WinRT (например, Boolean, Int32, String, Guid и т. д.)
- Перечисления WinRT
- Структуры WinRT
- Интерфейсы WinRT
- Делегаты WinRT
- Классы среды выполнения WinRT
- Другие параметризованные экземпляры типов (например,
IVector<IVector<int>>
) любой другой тип не может отображаться в списке аргументов параметризованного типа. Например, массивы.
Параметризованные экземпляры типов
Экземпляр параметризованного типа может отображаться в любом контексте, который может отображаться не параметризованным типом. Параметризованный экземпляр интерфейса можно использовать в любом месте, где может использоваться интерфейс, например в списке интерфейсов, реализованных классом среды выполнения. Параметризованный экземпляр делегата можно использовать в любом месте, где может использоваться делегат, например в определении события.
Параметризованный тип может отображаться: в параметризованном интерфейсе или определении делегата; или любое место, в которое обычно может отображаться обычный тип. Если параметр отображается, где может отображаться только интерфейс, этот параметр ограничен интерфейсом. Если параметр отображается в контексте, где может отображаться любой тип, этот параметр не ограничивается; и так далее. Аргументы для параметризованных экземпляров типов должны соответствовать всем таким ограничениям.
Создание guid для параметризованных типов
Алгоритм создания guid должен соответствовать этим требованиям.
- Если параметризованный тип создается дважды с одинаковыми аргументами, оба экземпляра должны быть назначены одному интерфейсу или телу делегата и одному и тому же идентификатору IID.
- Если создаются экземпляры двух разных параметризованных типов, даже с одними и теми же аргументами, они должны быть статистически маловероятны, что им назначен один и тот же IID.
- Если параметризованный тип создается дважды, но с разными аргументами, он должен быть статистически маловероятным, что двум экземплярам назначается один и тот же iiD.
Примечание
Не допускается создание экземпляра параметризованного типа с тем же экземпляром, что и аргумент, или в качестве аргумента для любого другого параметризованного типа, который отображается в списке аргументов (т. е. циклическое создание экземпляра). Например, если X = Foo<Y>
и Y = Foo<X>
, не циклическое значение было нарушено. Однако, если X = Foo<Y>
и Y = Foo<int>
, то не цикличность была сохранена.
Алгоритм создания экземпляров выглядит следующим образом.
- Каждому параметризованному типу присваивается параметризованный идентификатор интерфейса автором — сокращенный ИДЕНТИФИКАТОР PIID. Обратите внимание, что ИДЕНТИФИКАТОР PIID не является идентификатором IID и не передается в качестве аргумента в QueryInterface. Автор должен убедиться, что ИДЕНТИФИКАТОР PIID уникален параметризованным типом.
- Сигнатура типа для базового типа представляет собой строку октета ASCII (см. таблицу ниже). Например, Int32 имеет значение "i4".
- Сигнатура типа для интерфейса, не являющегося параметризованным экземпляром интерфейса, — это идентификатор IID, закодированный в ФОРМАТЕ ASCII в пунктирной форме и разделенный фигурными скобками. Например, {00000000-0000-0000-0000-000000000000}.
- Сигнатура типа для делегата, не являющегося параметризованным экземпляром делегата, является строкой "delegate", а затем iiD как с интерфейсами. Далее появится подробная грамматика.
- Guid для параметризованного типа вычисляется в соответствии с этой грамматикой.
- в соответствии с UUID rfc 4122 вычислите 5 sha-1, созданный хэш signature_octets. В этом случае используется один guid pinterface/pintergroup winrt в качестве пространства имен, как описано в rfc 4122/4.3, а также сигнатура pinterface/pintergroup и аргументы, с которыми он создается в виде строки имени.
- Экземпляр pinterface назначается этому guid и сигнатуре из 4.
signature_octets => guid_to_octets(wrt_pinterface_namespace) string_to_utf8_octets(ptype_instance_signature)
wrt_pinterface_namespace => "11f47ad5-7b73-42c0-abae-878b1e16adee"
ptype_instance_signature => pinterface_instance_signature | pdelegate_instance_ signature
pinterface_instance _signature => "pinterface(" piid_guid ";" args ")"
pdelegate_instance _signature => "pinterface(" piid_guid ";" args ")"
piid_guid => guid
args => arg | arg ";" args
arg => type_signature
type_signature => base_type_identifer | com_interface_signature | interface _signature | delegate_signature | interface_group_signature | runtime_class_signature | struct_signature | enum_signature | pinterface_instance_signature | pdelegate_instance_signature
com_interface_signature => "cinterface(IInspectable)"
base_type_identifier is defined below
interface_signature => guid
interface_group_signature => "ig(" interface_group_name ";" default_interface ")"
runtime_class_signature => "rc(" runtime_class_name ";" default_interface ")"
default_interface => type_signature
struct_signature => "struct(" struct_name ";" args ")"
enum_signature => "enum(" enum_name ";" enum_underlying_type ")"
enum_underlying_type => type_signature
delegate_signature => "delegate(" guid ")"
guid => "{" dashed_hex "}"
dashed_hex is the format that uuidgen writes in when passed no arguments.
dashed_hex => hex{8} "-" hex{4} "-" hex{4} "-" hex{4} "-" hex{12}
hex => [0-9a-f]
- При передаче экземпляра p-типа в качестве аргумента в anther pinterface сигнатура, вычисляемая на шаге 3, используется в качестве сигнатуры типа в элементе грамматики "pinterface_instance_signature" или "pdelegate_instance_signature", как это необходимо.
Эти имена используются для базовых типов при их появлении.
- UInt8 сопоставляется с "u1"
- Int32 сопоставляется с "i4"
- UInt32 сопоставляется с "u4"
- Int64 сопоставляется с "i8"
- UInt64 сопоставляется с "u8"
- Одинарные карты с "f4"
- Двойные карты с "f8"
- Логическое сопоставление с "b1"
- Обратите внимание, что для получения поддержки логического типа необходимо добавить
/Yc:wchar_t
, чтобы включить wchar_t как встроенный тип.
- Обратите внимание, что для получения поддержки логического типа необходимо добавить
- Char16 сопоставляется с "c2"
- Строка сопоставляется со строкой "string"
- Guid сопоставляется с "g16"
Указанные выше имена чувствительны к регистру. За исключением String, имя типа использует один символ, чтобы предложить тип данных, за которым следует его размер в байтах. Были выбраны следующие имена: чтобы быть краткими (чтобы избежать больших размеров в сигнатурах типов структуры); значение , чтобы не отображаться в запутанном виде как имя WinRT, имя RIDL, так и имя языковой проекции для любого типа; и по-прежнему оставаться примерно человеком удобочитаемым.
Для enum_type_signature единственным допустимым значением "underlying_type" является значение Int32 или UInt32.
Для struct_type_signature аргументы — это список type_signatures для полей структуры. Это могут быть базовые типы или другие типы структур.
Struct_name и enum_name являются пространством имен, используя точку "." в качестве разделителей. Например, "пространство имен X { структуры A{ int; }; }" становится "struct(X.A;i4)".
Default_interface должен быть экземпляром интерфейса, экземпляром P-интерфейса, делегатом или экземпляром P-делегата, который был указан в качестве значения по умолчанию в теле класса среды выполнения или группы интерфейсов с помощью атрибута IDL "[default]".
Обратите внимание, что пользовательские атрибуты игнорируются; предполагается, что маршалирование не оказывает никакого влияния.
Управление версиями
Все типы WinRT, кроме фундаментальных типов, должны иметь атрибут Version. Языковые проекции используют сведения об атрибуте Version для обеспечения обратной совместимости и для сценариев с освещением. Сторонние типы должны включать атрибут Version, но его необходимо игнорировать с помощью языковых проекций. Сторонние компоненты WinRT упаковываются исключительно в приложение, поэтому они никогда не могут изменять версию независимо от самого приложения.
Атрибут Version может применяться дополнительно к членам интерфейса (методам, свойствам и событиям). Это предназначено для высокоуровневой разработки классов в C#/VB и C++/CX. Атрибуты версии для членов интерфейса, даже Windows членов системного интерфейса, должны игнорироваться во время выполнения проекциями языка.
Атрибут Version содержит 32-разрядный 32-разрядный параметр конструктора целых чисел без знака. Для Windows типов WinRT это значение является значением NTDDI для версии Windows впервые определена конструкция связанного типа. Для сторонних типов значение этого значения равно автору типа.
Windows системные структуры, делегаты и интерфейсы неизменяемы после определения. Они никогда не могут быть изменены в любом последующем выпуске Windows.
Windows системные перечисления и классы среды выполнения являются аддитивно версиями. Перечисления могут добавлять новые значения перечисления в последующих выпусках Windows. Классы могут добавлять новые реализованные интерфейсы (включая статические, фабрику активации, фабрику композиции, переопределимые и защищенные интерфейсы) в последующих Windows выпусках. Дополнительные сведения об аддитивном управления версиями включаются в разделы для перечислений и классов среды выполнения.
Пространства имен
Пространство имен — это область именования, используемая для упорядочения кода и предотвращения конфликтов имен. Все именованные типы в системе типов WinRT (перечисления, структуры, делегаты, интерфейсы и классы среды выполнения) живут в пространстве имен. Пространство имен может содержать другие пространства имен.
Фундаментальные типы
Система типов WinRT включает основной набор встроенных примитивных типов.
Тип WinRT | Описание типа |
---|---|
Int16 | 16-разрядное целое число со знаком |
Int32 | 32-разрядное целое число со знаком |
Int64 | 64-разрядное целое число со знаком |
UInt8 | 8-разрядное целое число без знака |
UInt16 | 16-разрядное целое число без знака |
UInt32 | 32-разрядное целое число без знака |
UInt64 | 64-разрядное целое число без знака |
Один | 32-разрядное число с плавающей запятой IEEE 754 |
Double | 64-разрядное число с плавающей запятой IEEE 754 |
Char16 | 16-разрядное нечисловое значение, представляющее единицу кода UTF-16. |
Логическое | 8-разрядное логическое значение |
Строка | неизменяемая последовательность Char16 , используемая для представления текста |
Guid | 128-разрядный стандартный guid |
Перечисления
Тип enum представляет собой тип значения с набором именованных констант.
Каждый тип перечисления имеет соответствующий целочисленный тип, называемый базовым типом типа перечисления. Единственными юридическими базовыми типами перечисления в WinRT являются Int32 и UInt32.
Перечисление с базовым типом UInt32 должно содержать FlagsAttribute. Перечисление с базовым типом Int32 не должно содержать FlagsAttribute.
Перечисление должно иметь общедоступную видимость.
Перечисление версий
Перечисление является аддитивно версивируемым. Последующие версии заданного перечисления могут добавлять значения (также называемые именованными константами). Существующие значения не могут быть удалены или изменены. Значения перечисления при необходимости содержат значение VersionAttribute для различения при добавлении определенных значений в тип перечисления. Значения перечисления без versionAttribute считаются теми же значениями версии, что и заключенный тип перечисления.
Структуры
Структурой является тип записи с одним или несколькими полями. Структуры всегда передаются и возвращаются по значению. Поля структуры могут быть только примитивами, перечислениями, структурами, строками и IReference<T> (последние два — единственными двумя типами полей, выделенными кучи).
Структуры должны иметь общедоступную видимость.
Как правило, у структуры должно быть хотя бы одно поле (существуют редкие исключения, такие как типы, представляющие контракты метаданных и атрибуты). Все поля структуры должны быть общедоступными.
Структуры не могут быть универсальными и параметризованными.
Интерфейсы
Интерфейс — это контракт, состоящий из группы связанных элементов типа, использование которых определено, но реализация которой не является. Определение интерфейса указывает элементы интерфейса — методы, свойства и события. Реализация не связана с интерфейсом.
Не параметризованные интерфейсы должны иметь уникальный идентификатор интерфейса (aka IID), указанный с помощью GuidAttribute. Параметризованный интерфейс должен иметь уникальный параметризованный идентификатор интерфейса (также известный как PIID), указанный с помощью GuidAttribute. PIID используется для создания идентификатора IID для определенного параметризованного экземпляра интерфейса с помощью указанного выше алгоритма.
Интерфейс может иметь общедоступную или частную видимость. Это отражает тот факт, что некоторые интерфейсы представляют общие контракты, реализованные несколькими классами WinRT, а другие интерфейсы представляют члены, реализованные одним классом WinRT. Интерфейс частной видимости должен указать класс WinRT, который он является эксклюзивным через ExclusiveToAttribute. Частные интерфейсы могут быть реализованы только классом WinRT, указанным в ExclusiveToAttribute.
IInspectable и IUnknown
Когда речь идет об интерфейсах, WinRT не имеет понятия о наследовании. Вместо этого существует идея о том, что интерфейс может потребовать другого интерфейса. Дополнительные сведения, в частности о ключевом слове MIDL 3.0 requires
, см. в интерфейсах MIDL 3.0.
Все интерфейсы WinRT неявно требуют IInspectable; и, в свою очередь, IInspectable требует IUnknown. IUnknown определяет три метода: QueryInterface, AddRef и Release согласно традиционному использованию COM. IInspectable определяет три метода в дополнение к методам IUnknown: GetIids, GetRuntimeClassName и GetTrustLevel. Эти три метода позволяют клиенту объекта получать сведения об объекте. В частности, IInspectable.GetRuntimeClassName позволяет клиенту объекта получить имя типа WinRT, которое можно разрешить в метаданных для включения языковой проекции.
Требуется интерфейс
Как упоминалось выше, интерфейс может указать, что для него требуется один или несколько других интерфейсов, которые должны быть реализованы для любого объекта, реализующего рассматриваемый интерфейс. Например, если для IButton требуется IControl, то любому классу, реализующим IButton , также потребуется реализовать IControl.
Но ни система типов WinRT, ни ABI не имеют концепции наследования интерфейса. Таким образом, идея добавления новых функций путем реализации новых интерфейсов, наследуемых от существующих интерфейсов (например, IFoo2 наследует от IFoo) не имеет смысла. Верно, что проекция языка WinRT может использовать связь наследования для простоты потребления на этом конкретном языке, а класс среды выполнения может использовать наследование, но наследование интерфейса не существует в контексте разработки MIDL 3.0 (см. интерфейсы MIDL 3.0).
Параметризованные интерфейсы
Интерфейсы поддерживают параметризацию типов. Параметризованное определение интерфейса задает список параметров типа в дополнение к списку членов интерфейса и требуемых интерфейсов. Обязательный интерфейс параметризованного интерфейса может совместно использовать один и тот же список аргументов типа, чтобы указать параметризованный экземпляр интерфейса и интерфейса, который он требует (например, IVector<T> requires IIterable<T>
). Сигнатура любого элемента (то есть метода, свойства или события) параметризованного интерфейса может ссылаться на тип из списка аргументов типа параметризованного интерфейса (например, IVector<T>.SetAt([in] UInt32 index, [in] T value)
).
Сторонние пользователи не могут определять новые параметризованные интерфейсы. Поддерживаются только параметризованные интерфейсы, определенные системой.
Делегаты
Делегат — это тип WinRT, который выступает в качестве указателя на типобезопасную функцию. Делегат по сути является простым объектом WinRT, который предоставляет один интерфейс, наследуемый от IUnknown, и определяет один метод с именем Invoke. Вызов делегата, в свою очередь, вызывает метод, на который он ссылается. Делегаты часто (но не исключительно) используются для определения событий WinRT.
Делегат WinRT является именованным типом и определяет сигнатуру метода. Подписи методов делегата следуют тем же правилам для параметров, что и методы интерфейса. Имена подписей и параметров метода Invoke должны соответствовать определению делегата.
Как и интерфейсы, не параметризованные делегаты должны иметь уникальный идентификатор интерфейса (aka IID), указанный с помощью GuidAttribute. IID делегата используется в качестве iiD одного интерфейса метода, используемого для реализации делегата. Параметризованные делегаты должны иметь уникальный параметризованный идентификатор интерфейса (также известный как PIID), указанный с помощью GuidAttribute. PIID используется для создания идентификатора IID для конкретного параметризованного экземпляра делегата с помощью указанного выше алгоритма.
Делегат должен иметь общедоступную видимость.
IUnknown
Обратите внимание, что в отличие от интерфейсов WinRT делегаты реализуют IUnknown, но не IInspectable. Это означает, что их невозможно проверить на наличие сведений о типе во время выполнения.
Параметризованные делегаты
Делегаты поддерживают параметризацию типов. Параметризованное определение делегата задает список параметров типа в дополнение к традиционной сигнатуре метода, как указано выше. В сигнатуре метода любой параметр может быть указан как один из типов из списка аргументов типа параметризованных делегатов.
Сторонние пользователи не могут определять новые параметризованные делегаты. Поддерживаются только параметризованные делегаты, определенные системой.
Члены интерфейса
Интерфейсы WinRT поддерживают три типа элементов: методы, свойства и события. В интерфейсах могут не быть полей данных.
Методы
Интерфейсы WinRT поддерживают методы, которые принимают ноль или больше параметров, и возвращают hrESULT , указывающие на успешное или неудачное выполнение вызова метода. При необходимости метод может указывать одиночный параметр, который будет проецироваться в качестве возвращаемого значения на языках на основе исключений. Этот возвращаемый параметр, если он указан, должен быть последним параметром в сигнатуре метода.
Метод должен иметь общедоступную видимость.
Метод может не использовать переменные числа аргументов. Метод может не иметь необязательных параметров и параметров со значениями по умолчанию.
Метод не может быть параметризован. Параметризованные делегаты и методы параметризованных интерфейсов могут использовать параметры типа содержащего типа в сигнатуре метода.
Параметры
Все параметры метода, кроме параметров длины массива (описанные ниже), должны иметь имя и тип. Обратите внимание, что возвращаемые значения должны указывать имя так же, как и параметры. Имена параметров метода, включая имя возвращаемого типа, должны быть уникальными в пределах области метода.
Только параметры параметризованных делегатов и членов параметризованных интерфейсов могут указывать параметризованный тип для типа параметра. Методы могут не быть параметризованы по отдельности. Параметры всегда могут указывать параметризованные экземпляры типов (например, IVector<int>
) в качестве типа параметра.
Все параметры метода должны быть исключительно в параметрах или вне. Параметры входа и выхода не поддерживаются.
Хотя метод в интерфейсе WinRT должен возвращать HRESULT, метод может при необходимости указать, что его окончательный параметр out предназначен для использования в качестве возвращаемого значения, когда метод проецируется на языки на основе исключений. Такие параметры называются параметрами [out, retval] после синтаксиса MIDL, используемого для их объявления. Если указан параметр [out, retval], он должен быть последним параметром в сигнатуре метода.
Кроме [out, retval], необходимо отобразить в конце списка параметров, нет других требований к упорядочению для параметров out.
Параметры массива
Методы WinRT поддерживают соответствующие параметры массива. Массивы нельзя использовать только в качестве параметров. Они не могут быть автономными именованными типами, и их нельзя использовать в качестве типа поля структуры. Параметры массива можно использовать как in
и out
retval
параметры.
WinRT поддерживает параметры массива большинства типов WinRT, включая фундаментальные типы (включая строки и guid), структуры, перечисления, делегаты, интерфейсы и классы среды выполнения. Массивы других массивов не допускаются.
Так как они соответствуют требованиям, параметры массива всегда должны быть непосредственно предшествуют в списке параметров параметром для размера массива. Параметр размера массива должен быть UInt32. Параметр размера массива не имеет имени.
WinRT поддерживает три разных стиля передачи массивов.
- PassArray. Этот стиль используется, когда вызывающий объект предоставляет массив методу. В этом стиле параметр размера массива и параметр массива являются обоими
in
параметрами. - FillArray. Этот стиль используется, когда вызывающий объект предоставляет массив для заполнения метода до максимального размера массива. В этом стиле параметр размера массива является параметром
in
, а параметр массива является параметромout
. При использовании стиля FillArray параметр массива может дополнительно указать один из других параметров в качестве параметра длины массива. Подробные сведения приведены ниже. - ReceiveArray. Этот стиль используется, когда вызывающий объект получает массив, выделенный методом. В этом стиле параметр размера массива и параметр массива являются обоими
out
параметрами. Кроме того, параметр массива передается по ссылке (т. е. ArrayType**, а не ArrayType*).
Примечание
Сочетание параметра размера массива out
, но in
параметра массива недопустимо в WinRT.
Если параметр массива используется в качестве параметра [out, retval], параметр длины массива должен быть параметром out
, то есть только стиль ReceiveArray является допустимым для retval
массивов.
Параметр длины массива
Параметр массива стилей FillArray может дополнительно указать другой параметр в качестве параметра длины массива. Если обязательный параметр размера массива указывает максимальное количество элементов в массиве, предоставленном вызывающим элементом, параметр длины массива указывает количество элементов, которые фактически были заполнены вызывающим элементом.
Параметр длины массива задается с помощью атрибута LengthIs в параметре массива.
Перегрузка методов
В области одного интерфейса несколько методов могут иметь одно и то же имя. Методы с тем же именем в интерфейсе должны иметь уникальные сигнатуры. Свойства и события не могут быть перегружены.
WinRT поддерживает перегрузку типов параметров, но способствует перегрузке числа входных параметров, также известных как arity метода. Это делается для поддержки динамических слаботипизированных языков (таких как JavaScript).
Если интерфейс имеет несколько методов с одинаковыми именами и количеством входных параметров, то один из этих методов должен быть помечен как стандартный. Из всех перегруженных методов с одинаковым именем и количеством входных параметров только метод, помеченный как используемый по умолчанию, будет проецироваться динамическим слабо типизированным языком. Если существует только один перегруженный метод заданного имени и числа входных параметров, помечая его как допустимый по умолчанию, но не обязательно.
Для определения арности метода параметры массива и их обязательные параметры длины считаются одним параметром. Стили PassArray и FillArray считаются одним входным параметром, а стиль ReceiveArray считается одним выходным параметром.
Если несколько методов в интерфейсе имеют одинаковое имя, уникальное имя каждого метода столкновения должно храниться в overloadAttribute, присоединенном к методу. Перегруженные методы по умолчанию содержат defaultOverloadAttribute.
Перегрузка операторов
WinRT не поддерживает перегрузку операторов. Методы могут не называться с помощью специальных имен операторов, таких как op_Addition, указанные в спецификации ИНТЕРФЕЙСА командной строки ECMA 335, раздел I, раздел 10.3.
Свойства
Свойство — это пара методов get/set с соответствующим именем и типом, которые отображаются в некоторых языковых проекциях как поля, а не методы.
Свойство и его методы get/set должны иметь общедоступную видимость.
Свойство должно иметь get
метод. Метод получения свойства не имеет параметров и возвращает значение типа свойства. Свойство только с методом называется свойством get
только для чтения.
При необходимости свойство может иметь set
метод. Метод задания свойств имеет один параметр типа свойства и возвращает void. Свойство как с a get
, так и set
методом называется свойством чтения и записи.
Свойства не могут быть параметризованы. Свойства из параметризованных интерфейсов могут использовать параметры типа содержащего типа в качестве типа свойства.
События
Событие — это пара методов добавления и удаления прослушивателя с соответствующим именем и типом делегата. События — это механизм, позволяющий интерфейсу уведомлять заинтересованных сторон о том, что происходит что-то важное.
Событие и его методы добавления и удаления прослушивателя должны иметь общедоступную видимость.
Метод прослушивателя событий add
имеет один параметр типа делегата события и возвращает Windows. Foundation.EventRegistrationToken. Метод прослушивателя событий remove
имеет один параметр Windows. Тип Foundation.EventRegistrationToken и возвращает void.
События не могут быть параметризованы. События из параметризованных интерфейсов могут использовать параметры типа содержащего типа в качестве типа делегата события.
Классы среды выполнения
WinRT позволяет определить класс. Класс должен реализовывать один или несколько интерфейсов. Класс не может напрямую реализовывать члены типа (т. е. не может определять собственные методы, свойства и события). Класс должен предоставлять реализацию всех членов всех интерфейсов, которые он реализует.
Существует несколько различных типов интерфейсов, которые подробно описаны ниже.
- Интерфейсы-члены (включая защищенные и переопределимые интерфейсы)
- Статические интерфейсы
- Интерфейсы фабрики активации
- Интерфейсы фабрики композиции
Классы среды выполнения не могут быть параметризованы. Класс среды выполнения может реализовать параметризованный экземпляр интерфейса (т. е. параметризованный интерфейс со всеми заданными параметрами типа) в любом месте, где он обычно принимает не параметризованный интерфейс.
Класс среды выполнения должен иметь общедоступную видимость.
Класс среды выполнения может реализовывать только интерфейсы, которые не являются эксклюзивными (т. е. не переносят атрибут exclusiveTo) или являются эксклюзивными для класса среды выполнения. Класс среды выполнения не может реализовывать интерфейсы, которые являются эксклюзивными для другого класса среды выполнения. Существует одно исключение из этого правила— составной класс может реализовывать интерфейсы, которые являются эксклюзивными для класса в цепочке производных, помеченных как переопределяемые. Подробные сведения о переопределениях интерфейсов для выполнения.
Интерфейс члена
Класс среды выполнения может реализовывать ноль или несколько интерфейсов-членов. Интерфейсы-члены позволяют классам предоставлять функциональные возможности, связанные с экземплярами класса. Класс среды выполнения задает список интерфейсов элементов, которые он реализует. Записи в списке интерфейсов-членов, реализованных классом среды выполнения, могут дополнительно содержать сведения о версии. Подробные сведения о управления версиями классов среды выполнения для выполнения.
Интерфейсы-члены реализуются непосредственно на экземплярах класса среды выполнения.
Классы среды выполнения, реализующие один или несколько интерфейсов-членов, должны указывать один из интерфейсов-членов, который должен быть интерфейсом по умолчанию. Классы среды выполнения, реализующие ноль интерфейсов-членов, не указывают интерфейс по умолчанию.
Статические интерфейсы
Классы WinRT могут указывать ноль или больше статических интерфейсов. Статические интерфейсы позволяют классам предоставлять функциональные возможности, связанные с самим классом, а не с конкретными экземплярами класса.
Класс должен указывать по крайней мере один член или статический интерфейс. Класс без члена и не является недопустимым статическим интерфейсом.
Статические интерфейсы задаются с помощью StaticAttribute, связанного с классом среды выполнения. StaticAttribute содержит ссылку на ссылку на статический интерфейс, а также сведения о версии. Подробные сведения о управления версиями классов среды выполнения для выполнения.
Хотя статические интерфейсы объявляются как часть класса среды выполнения, они фактически не реализуются в самих экземплярах классов. Вместо этого они реализуются на фабрике активации класса. Подробные сведения о фабриках активации, которые следует следовать.
Активация
При необходимости классы среды выполнения поддерживают активацию — возможность системы создавать экземпляры указанного класса. Классы должны реализовывать по крайней мере один интерфейс-член для поддержки активации.
WinRT определяет три механизма активации: прямую активацию (без параметров конструктора), активацию фабрики (с одним или несколькими параметрами конструктора) и активацию композиции. Несочиняемые классы могут поддерживать прямую и (или) активацию фабрики. Составные классы поддерживают только компонуемую активацию. Подробные сведения о композиции и компонуемой активации для выполнения.
Классы, поддерживающие прямую активацию, активируются путем вызова метода IActivationFactory.ActivateInstance в фабрике активации класса. Этот метод не принимает параметров и возвращает только что активированный экземпляр класса среды выполнения. Подробные сведения о фабриках активации, которые следует следовать.
Классы, поддерживающие активацию фабрики, определяют один или несколько фабричные интерфейсы, каждый из которых, в свою очередь, определяет один или несколько методов фабрики. Эти фабричные интерфейсы реализуются на фабрике активации класса.
Методы фабрики принимают один или несколько in
параметров и должны возвращать только что активированный экземпляр класса среды выполнения. Другие out
параметры за пределами вновь активированного экземпляра класса не допускаются. Методы фабрики должны принимать один или несколько параметров. Активация фабрики без параметров запрещена. Прямая активация должна использоваться для активации без параметров.
Классы, поддерживающие прямую или заводную активацию, помечены атрибутом ActivationableAttribute. Параметр ActivationableAttribute содержит сведения о версии (сведения о версии класса среды выполнения для последующего выполнения), а также необязательную ссылку на интерфейс фабрики. Классы можно пометить несколькими атрибутами ActivationableAttributes ( не более одного для активации по умолчанию, а также по одному для каждого фабричного интерфейса, реализованного фабрикой активации класса). Классы, помеченные атрибутом ActivatableAttribute, также не могут быть помечены атрибутом ComposableAttribute. Подробные сведения о композиции для выполнения.
Компоновка
Классы среды выполнения при необходимости поддерживают композицию — возможность объединения нескольких экземпляров классов в то, что, как представляется, является одним объектом извне. WinRT использует композицию в качестве формы наследования классов среды выполнения.
При необходимости классы WinRT могут создавать один компонуемый базовый класс, который, в свою очередь, может создавать один составной базовый класс и т. д. Класс не должен быть компонуемым для создания составного базового класса. Классы могут создавать только составные классы в качестве базового класса. Компонуемый класс не требуется для создания другого компонуемого класса (т. е. это может быть корень иерархии). Циклические графы композиции (например, A composes B, которые составляют A) не допускаются.
Во время выполнения класс создания представляет собой агрегирование объектов WinRT — по одному для каждого объекта в цепочке композиции. Эти агрегированные объекты делегируют удостоверение и время существования первоначально активированного объекта в цепочке композиции (называемого управляемым объектом). Каждый объект в цепочке содержит ненаправленный указатель IInspectable на класс, который он создает, чтобы вызывать методы для интерфейсов составных базовых классов, включая методы защищенных интерфейсов. Каждый объект в цепочке имеет указатель на управляемый класс для делегирования времени существования и удостоверения, а также для вызова методов в переопределяемых интерфейсах. Сведения о защищенных и переопределиемых интерфейсах для выполнения.
Рассмотрим пример, в котором Кнопка создает элемент управления, который, в свою очередь, создает UIElement. В этом примере экземпляр Button агрегирует экземпляр элемента управления , который, в свою очередь, объединяет экземпляр UIElement . Все три объекта имеют ссылку на объект Button для управления временем существования и удостоверения, а также для запроса переопределяемых интерфейсов. Каждый объект имеет указатель IInspectable на создаваемый объект (Кнопка содержит указатель на элемент управления; Элемент управления содержит указатель на UIElement), чтобы иметь возможность вызывать методы интерфейсов, реализованных в составных классах, включая защищенные интерфейсы.
Класс не может реализовывать интерфейсы, определенные в классе, который он создает, или любой класс в цепочке композиции, если интерфейс не помечен как переопределяемый в компонуемом классе. Подробные сведения о переопределениях интерфейсов для выполнения.
Составной класс должен быть помечен одним или несколькими ComposableAttributes. ComposableAttribute содержит ссылку на интерфейс фабрики композиции — можно ли использовать методы фабрики композиции в интерфейсе фабрики композиции для управления активацией объекта, а также сведения о версии. Сведения об интерфейсах фабрики композиции и управления версиями для выполнения следующих операций. Класс можно пометить несколькими composableAttributes — по одному для каждого интерфейса фабрики композиции, реализованного фабрикой активации класса.
Языковая проекция JavaScript не поддерживает композицию классов. Таким образом, составные классы и классы, которые составляют составные классы, должны быть помечены атрибутом WebHostHiddenAttribute, указывающим, что JavaScript не должен пытаться проецировать эти типы.
Сторонние разработчики могут определять только классы, составляющие другие составные классы. Вы не можете определить собственный компонуемый корневой класс.
Компонуемая активация
Составной класс должен определять один или несколько интерфейсов фабрики композиции, которые, в свою очередь, реализуют один или несколько методов фабрики композиции. Интерфейсы фабрики композиции реализуются на фабрике активации класса. Подробные сведения о фабриках активации, которые следует следовать.
Интерфейс фабрики композиции используется для создания составных экземпляров класса. Компонуемый интерфейс фабрики объявляет ноль или более компонуемых методов фабрики, которые можно использовать для активации экземпляров класса в целях композиции. Обратите внимание, что у вас есть компонуемый интерфейс фабрики с нулевыми методами фабрики. Это означает, что класс можно использовать для композиции, но сторонние стороны могут не создавать класс напрямую, а методы для создания экземпляров являются внутренними.
Составной класс объявляет, можно ли использовать методы фабрики в заданном интерфейсе фабрики композиции для активации класса непосредственно в качестве управляемого объекта. Компонуемые фабричные интерфейсы, помеченные как открытые, могут использоваться для непосредственной активации класса в качестве управляемого объекта, а также косвенно для активации класса в виде составного объекта. Составные интерфейсы фабрики, помеченные как защищенные, могут использоваться только для косвенной активации класса в виде составного объекта. Составные классы всегда можно активировать как составные объекты.
Интерфейс фабрики композиции должен быть exclusiveto
классом среды выполнения, которым он реализуется.
Как и метод фабрики активации, метод фабрики композиции должен возвращать экземпляр компонуемого класса. Кроме того, метод фабрики композиции имеет два дополнительных параметра: управляемый параметр IInspectable* [in] и нераспределяющий параметр IInspectable** [out]. При необходимости у метода фабрики композиции могут быть дополнительные in
параметры. При указании дополнительные параметры должны находиться в начале сигнатуры метода, прежде чем указанные выше обязательные параметры. Метод фабрики композиции может не иметь дополнительных out
параметров за пределами нераспределяющих IInspectable** и возвращаемых параметров значения.
Когда компонуемый класс активируется для композиции (например, Control или UIElement при активации экземпляра Button ), указатель на объект, который управляет удостоверением и временем существования, передается через управляемый параметр IInspectable* [in]. Метод компонуемой фабрики возвращает вновь активированный экземпляр в качестве возвращаемого значения. Этот экземпляр делегирует все функции управления удостоверениями и временем существования в предоставленные функции управления IInspectable* . Кроме того, метод компонуемой фабрики возвращает указатель на неэлегирующий IInspectable* , который класс создания может использовать для вызова методов в составном классе.
При активации компонуемого класса в качестве управляемого класса (например, Button в предыдущем примере) используются те же методы компонуемой фабрики, что и для активации композиции. При активации компонуемого класса напрямую значение NULL передается для управляемого параметра *IInspectable* . Это индикатор компонуемого класса, который он активируется как управляемый класс. Когда управляемый класс создает экземпляр класса, который он создает, он передает ссылку на себя в качестве управляемого параметра IInspectable* . Метод компонуемой фабрики возвращает управляемый экземпляр класса в качестве возвращаемого значения. Неуправляемый параметр IInspectable** [out] игнорируется клиентским кодом при активации управляемого компонуемого класса.
Основываясь на предыдущем примере Button ->Control ->UIElement , класс кнопки будет активироваться путем вызова одного из методов фабрики композиции и передачи null для внешнего параметра. Кнопка , в свою очередь, активирует экземпляр Control , передав ссылку на себя в качестве внешнего параметра. Элемент управления , в свою очередь, активирует экземпляр UIElement , передав внешнюю ссылку, полученную в качестве внешнего параметра. Метод фабрики UIElement вернется к элементу Control вновь созданного uiElement в параметре экземпляра, а также ссылку на элемент UIElement без делегирования IInspectable во внутреннем параметре. Метод " Фабрика элементов управления " вернется к button вновь созданному элементу Control в параметре экземпляра, а также ссылке на элемент управления, не делегирующий IInspectable в внутреннем параметре. Фабрика композиции button вернется в вызывающий код только что созданной кнопки в параметре экземпляра и null для внутреннего параметра.
Иногда класс может быть активирован для композиции, а также в другие моменты активации в качестве управляемого класса. Например, если radioButton composed Button, кнопка будет активирована для композиции при активации RadioButton; но активируется как управляемый класс, когда кнопка была активирована напрямую. В любом случае класс Control , который создает Button , будет активирован для композиции.
Защищенные интерфейсы
Составной класс может объявлять ноль или больше его интерфейсов-членов для защиты. Не компонуемый класс может не объявлять интерфейсы-члены для защиты. Только код в классе, который создает компонуемый класс (прямо или косвенно), может запрашивать и использовать интерфейсы, которые компостируемый класс объявляет как защищенный. Код за пределами цепочки композиции не может запрашивать и не использовать интерфейсы, которые компонуемый класс объявляет как защищенный.
Например, если UIElement объявляет защищенный интерфейс IUIElementProtected, то могут запрашивать и использовать интерфейс IUIElement, состоящий только из классов, составляющих UIElement( включая прямую (control) и непрямую (button) композицию.
Переопределимые интерфейсы
Составной класс может объявлять ноль или больше его интерфейсов-членов, которые будут переопределяться. Переопределяемый интерфейс может запрашиваться только в цепочке композиции, аналогично правилам доступа к защищенным интерфейсам, описанным выше. Однако если защищенный интерфейс может быть реализован только классом, который первоначально объявил его, переопределяемые интерфейсы могут быть повторно реализованы классами, составляющими класс, реализующий переопределяемый интерфейс.
Во время выполнения любой компонуемый код класса, использующий переопределяемый интерфейс, должен запрашиватьInterface для интерфейса с помощью управляемого указателя IInspectable* , используемого для делегирования удостоверений и времени существования. Этот указатель возвращает реализацию переопределяемого интерфейса, который является самым ранним в цепочке композиции (то есть ближе всего к управляемому экземпляру класса). Класс, желающий получить доступ к переопределяемым интерфейсам класса, который он создает, может сделать это с помощью неэлегирующих ссылок, которые компонуемый класс содержит в его составном классе.
Рассмотрим пример, который UIElement объявляет переопределяемый интерфейс IUIElementOverridable. В этом случае классы, производные от UIElement, включая прямую (control) и непрямую (button) наследование, будут разрешены для его реализации. Если код в UIElement необходим для доступа к функциям IUIElementOverridable, UIElement запросит управляющую IInspectable , чтобы получить самую раннюю реализацию в цепочке композиции. Если элемент управления и кнопка реализовали IUIElementOverridable, то реализация button будет возвращена при запросе управляемого IInspectable . Если Кнопка хочет получить доступ к его функциональным возможностям составного класса, она может использовать нераспределяющий IInspectable , возвращенный методом фабрики композиции, для запроса базового класса для этого интерфейса.
Фабрики активации
Класс среды выполнения при необходимости имеет фабрику активации. Класс среды выполнения должен иметь фабрику активации, если класс активируется, компонуется или имеет статические интерфейсы. Фабрику активации для класса можно получить из системы во время выполнения с помощью функции RoGetActivationFactory Win32.
Фабрики активации должны реализовать интерфейс IActivationFactory . Однако только классы, поддерживающие прямую активацию, обеспечивают реализацию единого метода ActivateInstanceiActivationFactory. Классы, не поддерживающие прямую активацию, должны возвращать E_NOTIMPL из IActivationFactory.ActivateInstance.
Фабрика активации должна реализовывать все интерфейсы фабрики активации, интерфейсы фабрики композиции и статические интерфейсы, определенные в классе среды выполнения.
Не гарантируется, что языковые проекции поддерживают один экземпляр фабрики активации в течение всего времени существования фабрики. Авторы классов WinRT, которым требуется сохранить долгоживущие сведения для доступа к статическим членам, должны хранить их где-то за пределами фабрики активации.
Проекция на основе классов
Хотя WinRT в основном является моделью программирования на основе интерфейса, классы среды выполнения предоставляют модель программирования на основе классов, которая лучше соответствует современным, основным, объектно-ориентированным (OO) языкам программирования. Предполагается, что языковые проекции проецируют класс среды выполнения как единую сущность, а не как пакет интерфейсов, с которыми разработчик должен работать отдельно.
Для достижения этой модели на основе класса ожидается, что языковые проекции будут проектировать члены из интерфейсов членов класса в качестве прямых членов класса. Ожидается, что языковые проекции будут проектировать члены типа из статических интерфейсов класса в качестве членов статических классов. Наконец, предполагается, что языковые проекции будут проектировать методы активации (прямая активация, а также интерфейсы из интерфейсов фабрики и компонуемых фабрик) в качестве конструкторов классов.
Чтобы помочь в этой проекции на основе класса, метаданные классов среды выполнения указывают член класса для всех методов, свойств и событий из каждого реализуемого интерфейса. Каждый член класса явно привязывается к члену интерфейса, в котором он был первоначально определен. Это позволяет проекциям языка предоставлять класс как единую сущность, обрабатывая все запросы интерфейса и подсчет ссылок под обложками от имени разработчика.
По умолчанию каждый реализованный член интерфейса проецируется как член класса. Тем не менее, поскольку классы среды выполнения могут реализовывать несколько независимых интерфейсов и версий с течением времени (сведения о версиях, которые следует следовать), можно создавать конфликты имен для членов, определенных в разных интерфейсах, реализованных одним классом среды выполнения.
При возникновении конфликтов проекция члена класса по умолчанию невозможна. Если конфликты происходят между интерфейсами, добавленными в отдельных версиях, член, сталкивающийся с самой ранней версией, проецируется как член класса. При возникновении конфликтов между интерфейсами, добавленными в той же версии, ни один из конфликтующих элементов не проецируется как члены класса. Обратите внимание, что методы с именами, сталкивающимися, разрешены, если все версии имеют разные arity , как описано в перегрузке метода.
Элементы интерфейса, которые не проецируются как члены класса, должны быть доступны разработчикам. Как правило, это делается оператором приведения или динамического поиска, что позволяет разработчику указать конкретный интерфейс и метод, который они хотят вызвать.
Чтобы устранить конфликты имен методов, классы среды выполнения могут указывать альтернативные имена методов для элементов и статических интерфейсов, которые они реализуют. Это альтернативное имя используется проекцией языка для предоставления неоднозначного доступа к именам методов, сталкивающимся с экземпляром класса. Хотя класс среды выполнения может предоставить альтернативное имя метода, сигнатуру метода, параметры и любые атрибуты, присоединенные к методу или его атрибуты, по-прежнему должны точно соответствовать исходному определению интерфейса.
Так как прямые активации, методы фабрики и методы фабрики композиции проецируются как конструкторы классов, все они проецируются в классе среды выполнения так же, как если бы они имели одинаковое имя. Все методы во всех интерфейсах фабрики должны иметь уникальные сигнатуры, следует использовать перегрузку на основе arity по сравнению с перегрузкой на основе типов и использовать DefaultOverloadAttribute для устранения неоднозначности методов фабрики одного и того же arity.
Управление версиями классов
Классы среды выполнения являются аддитивно версиями. Последующие версии заданного класса среды выполнения могут указывать дополнительные интерфейсы всех типов, а также дополнительные сведения о отдельных типах интерфейсов ниже. Существующие интерфейсы, указанные классом, никогда не могут быть удалены или изменены без нарушения обратной совместимости.
Управление версиями интерфейсов членов
Интерфейсы членов в классах среды выполнения являются аддитивно версиями. Последующие версии заданного класса среды выполнения могут реализовывать дополнительные интерфейсы-члены, даже если класс ранее не реализовал интерфейсы членов. Последующие версии заданного класса среды выполнения могут реализовывать дополнительные защищенные и переопределяемые интерфейсы.
Интерфейсы, реализованные классом среды выполнения, при необходимости несут versionAttribute, чтобы различать, когда определенные интерфейсы были добавлены в тип класса среды выполнения. Значения реализации интерфейса без versionAttribute считаются теми же значениями версии, что и заключенный тип класса среды выполнения.
Управление версиями статических интерфейсов
Статические интерфейсы в классах среды выполнения являются аддитивно версиями. Последующие версии заданного класса среды выполнения могут реализовывать дополнительные статические интерфейсы, даже если класс ранее не реализовал статические интерфейсы.
StaticAttribute включает параметр UInt32 для номера версии, который определяет версию Windows, которая добавила поддержку активации.
Управление версиями активации
Поддержка активации классов среды выполнения является аддитивной версией. Последующие версии данного класса среды выполнения могут реализовывать дополнительные механизмы активации, даже если класс никогда не реализовал механизм активации. Обратите внимание, что составные классы не активируются, поэтому могут не добавлять поддержку активации.
Обратите внимание, что класс, поддерживающий прямую активацию, может добавлять только новые интерфейсы активации фабрики. Класс, который ранее поддерживал только активацию фабрики, может добавить поддержку прямой активации, а также новые интерфейсы активации фабрики.
Параметр ActivatableAttribute включает параметр UInt32 для номера версии. Номер версии для ActivationableAttribute определяет версию Windows, которая добавила поддержку активации.
Управление версиями композиции
Поддержка композиции для классов среды выполнения является аддитивной версией. Последующие версии заданного компонуемого класса среды выполнения могут реализовывать дополнительные механизмы композиции, если класс был определен как составной при его создании. Составные классы могут не добавлять поддержку активации.
ComposableAttribute включает параметр UInt32 для номера версии. Номер версии composableAttribute определяет версию Windows, которая добавила поддержку композиции.
Настраиваемые атрибуты
WinRT поддерживает определение настраиваемых атрибутов метаданных. Все конструкции в системе типов WinRT могут содержать настраиваемые атрибуты метаданных. Сюда входят все именованные типы (перечисления, структуры, делегаты, интерфейсы, классы и т. д.), а также отдельные элементы, содержащиеся в конструкциях типов (например, методы, параметры и т. д.).
Пользовательские атрибуты именуются как другие типы WinRT. Однако они не активируются. Они являются исключительно конструкцией данных.
Настраиваемые атрибуты определяют схему данных позиционных параметров или именованных полей. Настраиваемый атрибут может не использовать как позиционные параметры, так и именованные поля— он должен выбрать один или другой. Типы параметров и полей настраиваемого атрибута ограничены фундаментальными типами, перечислениями и ссылками на другие типы WinRT. Другие параметры или тип поля не допускаются.
Настраиваемые атрибуты, использующие позиционные параметры, должны определять один или несколько допустимых наборов позиционных параметров. Каждый набор должен указывать ноль или больше позиционных параметров. Экземпляр настраиваемого атрибута должен указывать один набор позиционных параметров, а также данные для каждого позиционного параметра в выбранном наборе.
Настраиваемый атрибут, использующий именованные поля, задает нулевые поля с именами и типами. Экземпляр настраиваемого атрибута должен указывать пары "имя-значение" для полей, которые необходимо указать. Экземпляр может указывать значения для всех, некоторых или ни одной из пар "имя-значение".
Он действителен для атрибута, который не имеет ни позиционных параметров, ни именованных полей.
Настраиваемый атрибут должен иметь общедоступную видимость.
Атрибут может указывать типы конструкций типов WinRT, с которыми он может быть связан с помощью AttributeUsageAttribute.
Сторонние пользователи не могут определять настраиваемые атрибуты. Поддерживаются только пользовательские атрибуты, определенные системой.