Système de types Windows Runtime (WinRT)
Remarques générales
Tous les types, à l’exception des types fondamentaux, doivent être contenus dans un espace de noms. Il n’est pas valide pour qu’un type se trouve dans l’espace de noms global.
Les types fournis par Windows sont tous contenus dans l’espace de noms Windows.* . Les types WinRT qui ne sont pas fournis par Windows (y compris les types WinRT fournis par d’autres parties de Microsoft) doivent vivre dans un espace de noms autre que Windows.*.
À l’exception des interfaces, tous les types WinRT doivent avoir une visibilité publique. Les interfaces WinRT peuvent éventuellement avoir une visibilité privée. Tous les autres types WinRT définis par l’utilisateur (structs, classes, énumérations, délégués, attributs) doivent avoir une visibilité publique.
WinRT ne prend pas en charge les types imbriqués. Aucun type WinRT ne peut inclure un autre type ; aucun type WinRT ne peut être imbriqué à l’intérieur d’un autre type.
Tous les aspects du système de type WinRT ne sont pas disponibles pour vous, en tant que développeur tiers.
WinRT prend en charge le paramétrage des interfaces et des délégués. Toutefois, dans cette version, WinRT ne prend pas en charge la définition de types paramétrables par les 3ème parties. Seuls les types paramétrables inclus dans le système dans l’espace de noms Windows.* sont pris en charge.
WinRT prend en charge la composition de classe en tant que mécanisme d’héritage runtime. Toutefois, dans cette version, WinRT ne prend pas en charge la définition d’une classe composable racine. Seules les classes composables racine incluses dans le système dans l’espace de noms Windows.* sont prises en charge.
Les espaces de noms winRT et les noms de types sont conservés dans la casse, mais insensibles, similaires au système de fichiers Windows et au Registre Windows. Cela signifie que vous ne pouvez pas avoir d’espaces de noms ou de noms de type qui varient uniquement par cas. Par exemple, vous ne pouvez pas avoir foo.SomeType et foo. AnotherType, et vous ne pouvez pas avoir foo.SomeType et Foo.someType.
Un identificateur WinRT doit être conforme à la grammaire suivante. Notez que seuls les caractères définis dans Unicode 3.0 et versions antérieures sont pris en charge.
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)
Types paramétrables
WinRT prend en charge le paramétrage de type des interfaces et des délégués. Les types paramétrables permettent à une famille d’interfaces d’être définies qui peuvent être traitées polymorphiques dans les langages de programmation qui prennent en charge la polymorphisme paramétrique.
Une instanciation de type paramétrable se produit lorsqu’un type paramétrable est spécifié avec une liste d’arguments de types dans un contexte de type, par exemple une position de paramètre de méthode. Par exemple, HRESULT foo(X<Y> x)
instancie le type paramétrable nommé par X avec le type Y comme premier et seul argument de type.
Une interface winRT non paramétrable ou un délégué est affecté à un GUID pour identifier de manière unique l’interface sous-jacente comme distincte d’autres interfaces sur le même objet. Une interface paramétrable (par exemple) IVector<T>
ou déléguée (par exemple) EventHandler<T>
est affectée à une ID d’interface paramétrable (PIID), qui est un GUID qui identifie de manière unique ce type paramétrable. Ce n’est pas un IID. Ce GUID est utilisé pour générer des IID pour les instances de type paramétrables (par exemple). IVector<int>
Liste d’arguments de type paramétrable
Ces types WinRT sont autorisés à apparaître dans la liste d’arguments d’un type paramétrable.
- Types fondamentaux WinRT (par exemple, Boolean, Int32, String, Guid, etc.)
- Énumérations WinRT
- Structs WinRT
- Interfaces WinRT
- Délégués WinRT
- Classes d’exécution WinRT
- Autres instanciations de type paramétrable (par exemple)
IVector<IVector<int>>
Tout autre type est interdit d’apparaître dans une liste d’arguments de type paramétrable. Par exemple, les tableaux.
Instances de type paramétrables
Une instance de type paramétrable peut apparaître dans n’importe quel contexte qu’un type non paramétrable peut apparaître. Une instance d’interface paramétrable peut être utilisée n’importe où une interface peut être utilisée, comme dans la liste des interfaces implémentées par une classe runtime. Une instance de délégué paramétrable peut être utilisée n’importe où un délégué peut être utilisé, par exemple dans la définition d’un événement.
Un paramètre de type paramétrable peut apparaître : dans l’interface paramétrable ou la définition de délégué ; ou, n’importe quel endroit qu’un type normal peut normalement apparaître. Si un paramètre apparaît où seule une interface peut apparaître, ce paramètre est limité à une interface. Si un paramètre apparaît dans un contexte où n’importe quel type peut apparaître, ce paramètre n’est pas limité ; et ainsi de suite. Les arguments pour les instances de type paramétrables doivent respecter toutes ces restrictions.
Génération de guid pour les types paramétrables
L’algorithme de génération guid doit répondre à ces exigences.
- Lorsqu’un type paramétré est instancié deux fois avec les mêmes arguments, les deux instanciations doivent être affectées au même corps d’interface ou de délégué, ainsi qu’au même IID.
- Si deux types paramétrables différents sont instanciés, même avec les mêmes arguments, il doit être statistiquement peu probable qu’ils soient affectés au même ID IID.
- Si un type paramétré est instancié deux fois, mais avec des arguments différents, il doit être statistiquement peu probable que les deux instanciations sont affectées au même IID.
Notes
Il n’est pas autorisé à instancier un type paramétré avec la même instanciation qu’un argument, ou en tant qu’argument à un autre type paramétré qui apparaît dans la liste d’arguments (c’est-à-dire, instanciation circulaire). Par exemple, si X = Foo<Y>
, et Y = Foo<X>
, la non-circulaire a été violée. Toutefois, si X = Foo<Y>
et , alors Y = Foo<int>
la non-circulaire a été maintenue.
L’algorithme d’instanciation est le suivant.
- Chaque type paramétrable est affecté à un ID d’interface paramétrable par son auteur , abrégé PIID. Notez qu’un PIID n’est pas un ID IID, ni qu’il n’est pas passé en tant qu’argument à QueryInterface. L’auteur doit s’assurer que le PIID est unique au type paramétrable.
- La signature de type d’un type de base est une chaîne d’octet ASCII (voir le tableau ci-dessous). Par exemple, Int32 est « i4 ».
- La signature de type d’une interface qui n’est pas une instance d’interface paramétrable est son IID encodé en ASCII sous forme en tirets, et délimitée par des accolades. par exemple, « {00000000-0000-0000-0000-000000000000} ».
- La signature de type d’un délégué qui n’est pas une instance de délégué paramétrable est la chaîne « délégué », puis l’IID comme avec les interfaces. La grammaire détaillée s’affiche ensuite.
- Le guid d’un type paramétrable est calculé en fonction de cette grammaire.
- selon UUID rfc 4122, calculez le hachage généré ver 5 sha-1 de signature_octets: cela utilise un guid pinterface/pintergroup unique comme décrit dans rfc 4122/4.3, et la signature du pinterface/pintergroup et les args qu’il est instancié avec comme chaîne de nom.
- l’instanciation pinterface est affectée à ce guid et la signature de 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]
- Lorsqu’une instanciation de type p est passée en tant qu’argument à un autre pinterface, la signature calculée à l’étape 3 est utilisée comme signature de type dans l’élément de grammaire « pinterface_instance_signature » ou « pdelegate_instance_signature », selon le cas.
Ces noms sont utilisés pour les types de base lorsqu’ils apparaissent.
- UInt8 est mappé à « u1 »
- Int32 est mappé à « i4 »
- UInt32 est mappé à « u4 »
- Int64 mappe à « i8 »
- UInt64 est mappé à « u8 »
- Cartes uniques à « f4 »
- Double mappage à « f8 »
- Boolean mappe à « b1 »
- Notez que, pour obtenir la prise en charge des paramètres de type booléen , vous devez ajouter
/Yc:wchar_t
pour activer wchar_t en tant que type intégré.
- Notez que, pour obtenir la prise en charge des paramètres de type booléen , vous devez ajouter
- Char16 est mappé à « c2 »
- Chaîne est mappée à « string »
- Guid mappe à « g16 »
Les noms ci-dessus respectent la casse. À l’exception de String, le nom de type utilise un caractère unique pour suggérer le type de données, suivi de sa taille en octets. Ces noms ont été choisis : pour être concis (pour éviter les grandes tailles dans les signatures de type de struct); pour ne pas sembler déroutant comme le nom WinRT, le nom RIDL, ni le nom de projection de langue pour n’importe quel type; et encore à rester à peu près lisible par l’homme.
Pour enum_type_signature, la seule valeur « underlying_type » valide est celle d’Int32 ou UInt32.
Pour struct_type_signature, args est une liste dans l’ordre des type_signatures pour les champs du struct. Il peut s’agir de types de base ou d’autres types de struct.
Struct_name et enum_name sont qualifiés pour l’espace de noms, à l’aide de la période « ». En tant que délimiteurs. Par exemple, « espace de noms X { struct A{ int; }; } » devient « struct(X.A;i4) ».
Default_interface doit être l’interface, l’instance p-interface, le délégué ou l’instance de délégué p qui a été spécifiée comme valeur par défaut dans le corps de la classe runtime ou du groupe d’interface, à l’aide de l’attribut IDL '[default]'.
Notez que les attributs personnalisés sont ignorés ; présumé ne pas avoir d’effet sur le marshaling.
Gestion de version
Tous les types WinRT, à l’exception des types fondamentaux, doivent avoir un attribut Version. Les projections de langage utilisent les informations d’attribut Version pour activer la compatibilité descendante et pour les scénarios d’éclairage. Les types tiers doivent inclure un attribut Version, mais ils doivent être ignorés par les projections de langage. Les composants WinRT tiers sont exclusivement empaquetés dans l’application, de sorte qu’ils ne peuvent jamais modifier la version indépendamment de l’application elle-même.
L’attribut Version peut éventuellement être appliqué aux membres de l’interface (méthodes, propriétés et événements). Cela est destiné à la création de classes de haut niveau en C#/VB et C++/CX. Les attributs de version sur les membres de l’interface, même Windows membres de l’interface système, doivent être ignorés lors de l’exécution par projections de langage.
L’attribut Version inclut un paramètre de constructeur entier 32 bits non signé. Pour Windows types WinRT, cette valeur est la valeur NTDDI de la version de Windows la construction de type associée a été définie pour la première fois. Pour les types tiers, la signification de cette valeur est à l’auteur du type.
Windows structs système, délégués et interfaces sont immuables une fois définis. Ils ne peuvent jamais être modifiés dans une version ultérieure de Windows.
Windows les énumérations système et les classes d’exécution peuvent être de manière additive. Les énumérations peuvent ajouter de nouvelles valeurs d’énumération dans les versions ultérieures de Windows. Les classes peuvent ajouter de nouvelles interfaces implémentées (notamment statiques, fabrique d’activation, fabrique de composition, interfaces substituables et protégées) dans les versions ultérieures de Windows. Des détails supplémentaires sur le contrôle de version additif sont inclus dans les sections pour les énumérations et les classes runtime.
Espaces de noms
Un espace de noms est une étendue d’affectation de noms utilisée pour organiser le code et éviter les collisions de nommage. Tous les types nommés dans le système de types WinRT (énumérations, structs, délégués, interfaces et classes runtime) résident dans un espace de noms. Un espace de noms peut contenir d’autres espaces de noms.
Types fondamentaux
Le système de type WinRT comprend un ensemble principal de types primitifs intégrés.
Type WinRT | Description du type |
---|---|
Int16 | entier signé 16 bits |
Int32 | entier signé 32 bits |
Int64 | entier signé 64 bits |
UInt8 | entier non signé 8 bits |
UInt16 | entier non signé 16 bits |
UInt32 | entier non signé 32 bits |
UInt64 | entier non signé 64 bits |
Unique | un nombre à virgule flottante IEEE 754 32 bits |
Double | un nombre à virgule flottante IEEE 754 64 bits |
Char16 | valeur non numérique 16 bits représentant une unité de code UTF-16 |
Booléen | valeur booléenne 8 bits |
String | séquence immuable de Char16 utilisée pour représenter du texte |
Guid | Guid standard 128 bits |
Énumérations
Un type enum est un type valeur distinct avec un ensemble de constantes nommées.
Chaque type d’énumération a un type intégral correspondant appelé type sous-jacent du type d’énumération. Les seuls types sous-jacents d’énumération légale dans WinRT sont Int32 et UInt32.
Une énumération avec un type sous-jacent d’UInt32 doit porter flagsAttribute. Une énumération avec un type sous-jacent d’Int32 ne doit pas porter flagsAttribute.
Une énumération doit avoir une visibilité publique.
Contrôle de version d’énumération
Une énumération peut être versionnée de manière additive. Les versions ultérieures d’une énumération donnée peuvent ajouter des valeurs (également appelées constantes nommées). Les valeurs préexistantes peuvent ne pas être supprimées ou modifiées. Les valeurs d’énumération comportent éventuellement la versionAttribute pour distinguer quand des valeurs spécifiques ont été ajoutées au type d’énumération. Les valeurs d’énumération sans versionAttribute sont considérées comme ayant la même valeur de version que le type d’énumération englobant.
Structures
Un struct est un type d’enregistrement avec un ou plusieurs champs. Les structs sont toujours passés et retournés par valeur. Les champs de struct peuvent uniquement être des primitives, des énumérations, des structs, des chaînes et IReference<T> (les deux derniers étant les deux seuls types de champs alloués au tas).
Les structs doivent avoir une visibilité publique.
En général, un struct doit avoir au moins un champ (il existe des exceptions rares, telles que des types représentant des contrats de métadonnées et des attributs). Tous les champs d’un struct doivent être publics.
Un struct ne peut pas être générique ni paramétré.
Interfaces
Une interface est un contrat qui se compose d’un groupe de membres de type connexes dont l’utilisation est définie, mais dont l’implémentation n’est pas. Une définition d’interface spécifie les membres de l’interface : méthodes, propriétés et événements. Aucune implémentation n’est associée à une interface.
Les interfaces non paramétrables doivent avoir un ID d’interface unique (également appelé IID) spécifié via un GuidAttribute. Une interface paramétrable doit avoir un ID d’interface paramétrable unique (également appelé PIID) spécifié via un GuidAttribute. Le PIID est utilisé pour générer un IID pour une instance d’interface paramétrable spécifique via l’algorithme spécifié ci-dessus.
Une interface peut avoir une visibilité publique ou privée. Cela reflète le fait que certaines interfaces représentent des contrats partagés implémentés par plusieurs classes WinRT, tandis que d’autres interfaces représentent des membres implémentés par une seule classe WinRT. Une interface de visibilité privée doit spécifier la classe WinRT à laquelle elle est exclusive via ExclusiveToAttribute. Les interfaces privées peuvent uniquement être implémentées par la classe WinRT spécifiée dans ExclusiveToAttribute.
IInspectable et IUnknown
En ce qui concerne les interfaces, WinRT n’a aucune notion d’héritage. Au lieu de cela, il existe l’idée qu’une interface peut nécessiter une autre interface. Pour plus d’informations, en particulier sur le mot clé MIDL 3.0 requires
, consultez les interfaces MIDL 3.0.
Toutes les interfaces WinRT nécessitent implicitement IInspectable ; et à son tour IInspectable nécessite IUnknown. IUnknown définit trois méthodes : QueryInterface, AddRef et Release en fonction de l’utilisation traditionnelle de COM. IInspectable définit trois méthodes en plus des méthodes IUnknown : GetIids, GetRuntimeClassName et GetTrustLevel. Ces trois méthodes permettent au client de l’objet de récupérer des informations sur l’objet. En particulier, IInspectable.GetRuntimeClassName permet au client d’un objet de récupérer un nom de type WinRT qui peut être résolu dans les métadonnées pour activer la projection de langage.
L’interface nécessite
Comme mentionné ci-dessus, une interface peut spécifier qu’elle nécessite une ou plusieurs autres interfaces qui doivent être implémentées sur n’importe quel objet qui implémente l’interface en question. Par exemple, si IButton requiert IControl, toute classe implémentant IButton doit également implémenter IControl.
Mais ni le système de type WinRT ni l’ABI n’a un concept d’héritage d’interface. Ainsi, l’idée d’ajouter de nouvelles fonctionnalités en implémentant de nouvelles interfaces qui héritent d’interfaces existantes (par exemple, IFoo2 hérite d’IFoo) n’a aucune signification. Il est vrai qu’une projection de langage WinRT peut utiliser une relation d’héritage pour faciliter la consommation dans ce langage particulier, et qu’une classe runtime peut utiliser l’héritage, mais l’héritage d’interface n’existe pas dans le contexte de la création MIDL 3.0 (voir interfaces MIDL 3.0).
Interfaces paramétrables
Les interfaces prennent en charge le paramétrage de type. Une définition d’interface paramétrable spécifie une liste de paramètres de type en plus de la liste des membres de l’interface et des interfaces requises. Une interface requise d’une interface paramétrable peut partager la même liste d’arguments de type, de sorte qu’un seul argument de type est utilisé pour spécifier l’instance paramétrable de l’interface et l’interface requise (par exemple). IVector<T> requires IIterable<T>
La signature de n’importe quel membre (autrement dit, méthode, propriété ou événement) d’une interface paramétrable peut référencer un type à partir de la liste des arguments de type de l’interface paramétrable (par exemple IVector<T>.SetAt([in] UInt32 index, [in] T value)
).
Les tiers ne peuvent pas définir de nouvelles interfaces paramétrables. Seules les interfaces paramétrables définies par le système sont prises en charge.
Délégués
Un délégué est un type WinRT qui agit comme pointeur de fonction de type sécurisé. Un délégué est essentiellement un objet WinRT simple qui expose une interface unique qui hérite d’IUnknown et définit une méthode unique nommée Invoke. L’appel du délégué appelle à son tour la méthode qu’il référence. Les délégués sont souvent (mais pas exclusivement) utilisés pour définir des événements WinRT.
Un délégué WinRT est un type nommé et définit une signature de méthode. Les signatures de méthode déléguée suivent les mêmes règles pour les paramètres que les méthodes d’interface. Les noms de signature et de paramètre de la méthode Invoke doivent correspondre à la définition du délégué.
Comme les interfaces, les délégués non paramétrés doivent avoir un ID d’interface unique (aka IID) spécifié via un GuidAttribute. L’IID du délégué est utilisé comme IID de l’interface de méthode unique utilisée pour implémenter le délégué. Les délégués paramétrés doivent avoir un ID d’interface paramétrable unique (également appelé PIID) spécifié via un GuidAttribute. Le PIID est utilisé pour générer un IID pour une instance déléguée paramétrable spécifique via l’algorithme spécifié ci-dessus.
Un délégué doit avoir une visibilité publique.
IUnknown
Notez que, contrairement aux interfaces WinRT, les délégués implémentent IUnknown, mais pas IInspectable. Cela signifie qu’ils ne peuvent pas être inspectés pour les informations de type au moment de l’exécution.
Délégués paramétrés
Les délégués prennent en charge le paramétrage de type. Une définition de délégué paramétrable spécifie une liste de paramètres de type en plus de la signature de méthode traditionnelle, comme indiqué ci-dessus. Dans la signature de méthode, tout paramètre peut être spécifié comme l’un des types de la liste des arguments de type des délégués paramétrés.
Les tiers ne peuvent pas définir de nouveaux délégués paramétrables. Seuls les délégués paramétrés définis par le système sont pris en charge.
Membres d’interfaces
Les interfaces WinRT prennent en charge trois types de membres : méthodes, propriétés et événements. Les interfaces peuvent ne pas avoir de champs de données.
Méthodes
Les interfaces WinRT prennent en charge les méthodes qui prennent zéro ou plusieurs paramètres, et qui retournent un HRESULT indiquant la réussite ou l’échec de l’appel de méthode. Une méthode peut éventuellement indiquer un paramètre unique à projeter comme valeur de retour dans les langues basées sur des exceptions. Ce paramètre de retour doit être le dernier paramètre de la signature de méthode.
Une méthode doit avoir une visibilité publique.
Une méthode peut ne pas utiliser de nombres variables d’arguments. Une méthode peut ne pas avoir de paramètres facultatifs, ni de paramètres avec des valeurs par défaut.
Une méthode peut ne pas être paramétrable. Les délégués paramétrables et les méthodes des interfaces paramétrables peuvent utiliser des paramètres de type du type contenant dans la signature de méthode.
Paramètres
Tous les paramètres de méthode à l’exception des paramètres de longueur du tableau (décrits ci-dessous) doivent avoir un nom et un type. Notez que les valeurs de retour doivent spécifier un nom comme les paramètres. Les noms de paramètres de méthode, y compris le nom du type de retour, doivent être uniques dans l’étendue de la méthode.
Seuls les paramètres des délégués paramétrables et des membres des interfaces paramétrables peuvent spécifier un type paramétrable pour le type de paramètre. Les méthodes peuvent ne pas être paramétrées individuellement. Les paramètres peuvent toujours spécifier des instances de type paramétrables (par exemple) IVector<int>
comme type de paramètre.
Tous les paramètres de méthode doivent être exclusivement dans ou hors paramètres. Les paramètres in/out ne sont pas pris en charge.
Alors qu’une méthode sur une interface WinRT doit retourner un HRESULT, une méthode peut éventuellement indiquer que son paramètre final out est destiné à être utilisé comme valeur de retour lorsque la méthode est projetée dans des langages basés sur des exceptions. Ces paramètres sont appelés paramètres [out, retval] après la syntaxe MIDL utilisée pour les déclarer. Lorsqu’un paramètre [out, retval] est spécifié, il doit être le dernier paramètre de la signature de méthode.
En dehors de [out, retval] nécessitant d’apparaître à la fin de la liste des paramètres, il n’existe pas d’autres exigences de classement pour les paramètres sortants.
Paramètres de tableau
Les méthodes WinRT prennent en charge les paramètres de tableau conformes. Les tableaux ne peuvent jamais être utilisés à l’exception des paramètres. Ils ne peuvent pas être des types nommés autonomes et ils ne peuvent pas être utilisés comme type de champ de struct. Les paramètres de tableau peuvent être utilisés comme in
, out
et retval
les paramètres.
WinRT prend en charge les paramètres de tableau de la plupart des types WinRT, notamment les types fondamentaux (y compris la chaîne et le guid), les structs, les énumérations, les délégués, les interfaces et les classes runtime. Les tableaux d’autres tableaux ne sont pas autorisés.
Étant donné qu’ils sont conformes, les paramètres de tableau doivent toujours être précédés immédiatement dans la liste des paramètres par un paramètre pour la taille du tableau. Le paramètre de taille du tableau doit être un UInt32. Le paramètre de taille du tableau n’a pas de nom.
WinRT prend en charge trois styles de passage de tableau différents.
- PassArray. Ce style est utilisé lorsque l’appelant fournit un tableau à la méthode. Dans ce style, le paramètre de taille du tableau et le paramètre de tableau sont les deux
in
paramètres. - FillArray. Ce style est utilisé lorsque l’appelant fournit un tableau pour la méthode à remplir, jusqu’à une taille maximale de tableau. Dans ce style, le paramètre de taille du tableau est un
in
paramètre, tandis que le paramètre de tableau est unout
paramètre. Lorsque vous utilisez le style FillArray, le paramètre de tableau peut éventuellement spécifier l’un des autres paramètres comme paramètre de longueur du tableau. Consultez les détails ci-dessous. - ReceiveArray. Ce style est utilisé lorsque l’appelant reçoit un tableau alloué par la méthode. Dans ce style, le paramètre de taille du tableau et le paramètre de tableau sont les deux
out
paramètres. En outre, le paramètre de tableau est passé par référence (autrement dit, ArrayType**, plutôt que ArrayType*).
Notes
La combinaison d’un out
paramètre de taille de tableau, mais d’un in
paramètre de tableau, n’est pas valide dans WinRT.
Lorsqu’un paramètre de tableau est utilisé comme paramètre [out, retval] , le paramètre de longueur du tableau doit être un out
paramètre, autrement dit, seul le style ReceiveArray est légal pour retval
les tableaux.
Paramètre de longueur du tableau
Un paramètre de tableau de style FillArray peut éventuellement spécifier un autre paramètre comme paramètre de longueur du tableau. Lorsque le paramètre de taille du tableau requis spécifie le nombre maximal d’éléments d’un tableau fourni par l’appelant, le paramètre de longueur du tableau spécifie le nombre d’éléments qui ont été réellement renseignés par l’appelant.
Le paramètre de longueur du tableau est spécifié avec l’attribut LengthIs sur le paramètre de tableau.
Surcharge de méthode
Dans l’étendue d’une seule interface, plusieurs méthodes peuvent avoir le même nom. Les méthodes portant le même nom sur une interface doivent avoir des signatures uniques. Les propriétés et les événements ne peuvent pas être surchargés.
WinRT prend en charge la surcharge sur les types de paramètres, mais favorise la surcharge sur le nombre de paramètres d’entrée, également appelée arité de la méthode. Cela est effectué pour prendre en charge des langages dynamiques et faiblement typés (tels que JavaScript).
Lorsqu’une interface a plusieurs méthodes du même nom et du même nombre de paramètres d’entrée, l’une de ces méthodes doit être marquée comme valeur par défaut. De toutes les méthodes surchargées portant le même nom et le même nombre de paramètres d’entrée, seule la méthode marquée comme la valeur par défaut sera projetée par un langage dynamique et faiblement typé. S’il n’existe qu’une seule méthode surchargée d’un nom donné et le nombre de paramètres d’entrée, le marquage comme valeur par défaut est valide, mais pas obligatoire.
Pour déterminer l’arité d’une méthode, les paramètres de tableau et leur paramètre de longueur requis sont considérés comme un seul paramètre. Les styles PassArray et FillArray sont considérés comme un paramètre d’entrée unique, tandis que le style ReceiveArray est considéré comme un paramètre de sortie unique.
Lorsque plusieurs méthodes sur une interface ont le même nom, un nom unique pour chaque méthode de collision doit être stocké dans une méthode OverloadAttribute attachée à la méthode. Les méthodes surchargées par défaut portent defaultOverloadAttribute.
Surcharge d’opérateur
WinRT ne prend pas en charge la surcharge des opérateurs. Les méthodes ne peuvent pas être nommées à l’aide des noms d’opérateur spéciaux tels que op_Addition spécifiés dans la spécification CLI ECMA 335, partition I, section 10.3.
Propriétés
Une propriété est une paire de méthodes get/set avec un nom et un type correspondants qui apparaissent dans certaines projections de langage comme des champs plutôt que des méthodes.
Une propriété et ses méthodes get/set doivent avoir une visibilité publique.
Une propriété doit avoir une get
méthode. Une méthode getter de propriété n’a aucun paramètre et retourne une valeur du type de propriété. Une propriété avec une get
seule méthode est appelée propriété en lecture seule.
Une propriété peut éventuellement avoir une set
méthode. Une méthode setter de propriétés a un seul paramètre du type de propriété et retourne void. Une propriété avec une get
méthode et une set
méthode est appelée propriété en lecture/écriture.
Les propriétés peuvent ne pas être paramétrées. Les propriétés des interfaces paramétrables peuvent utiliser des paramètres de type du type contenant comme type de propriété.
Événements
Un événement est une paire de méthodes d’écouteur d’ajout/suppression avec un nom et un type délégué correspondants. Les événements sont un mécanisme permettant à l’interface de notifier les parties intéressées lorsqu’une chose d’importance se produit.
Un événement et ses méthodes d’écouteur d’ajout/suppression doivent avoir une visibilité publique.
Une méthode d’écouteur d’événements add
a un seul paramètre du type délégué d’événement et retourne un Windows. Foundation.EventRegistrationToken. Une méthode d’écouteur d’événements remove
a un paramètre unique du Windows. Type Foundation.EventRegistrationToken et retourne void.
Les événements peuvent ne pas être paramétrés. Les événements provenant d’interfaces paramétrables peuvent utiliser des paramètres de type du type contenant comme type délégué d’événement.
Classes runtime
WinRT vous permet de définir une classe. Une classe doit implémenter une ou plusieurs interfaces. Une classe ne peut pas implémenter directement les membres de type (autrement dit, il ne peut pas définir ses propres méthodes, propriétés ni événements). Une classe doit fournir une implémentation de tous les membres de toutes les interfaces qu’il implémente.
Il existe plusieurs types d’interfaces différents, qui sont décrits en détail ci-dessous.
- Interfaces membres (y compris les interfaces protégées et substituables)
- Interfaces statiques
- Interfaces de fabrique d’activation
- Interfaces de fabrique de composition
Impossible de paramétrer les classes runtime. Une classe runtime peut implémenter une instance d’interface paramétrable (autrement dit, une interface paramétrable avec tous ses paramètres de type spécifiés) n’importe où elle accepterait généralement une interface non paramétrable.
Une classe runtime doit avoir une visibilité publique.
Une classe runtime peut implémenter uniquement des interfaces qui ne sont pas exclusives (autrement dit, ne transportent pas l’attribut exclusiveTo) ou qui sont exclusives à la classe runtime en question. Une classe runtime peut ne pas implémenter d’interfaces exclusives à une autre classe runtime. Il existe une exception à cette règle : une classe composable peut implémenter des interfaces exclusives à une classe dans sa chaîne de dérivation marquée comme substituable. Détails sur les interfaces substituables à suivre.
Interface membre
Une classe runtime peut implémenter zéro ou plusieurs interfaces membres. Les interfaces membres permettent aux classes d’exposer des fonctionnalités associées à des instances de la classe. Une classe runtime spécifie une liste des interfaces membres qu’il implémente. Les entrées de la liste des interfaces membres implémentées par une classe runtime peuvent éventuellement contenir des informations de version. Détails sur le contrôle de version de classe runtime à suivre.
Les interfaces membres sont implémentées directement sur les instances de la classe runtime.
Les classes runtime qui implémentent une ou plusieurs interfaces membres doivent spécifier l’une des interfaces membres pour être l’interface par défaut. Les classes runtime qui implémentent des interfaces membres zéro ne spécifient pas d’interface par défaut.
Interfaces statiques
Les classes WinRT peuvent spécifier zéro ou plusieurs interfaces statiques. Les interfaces statiques permettent aux classes d’exposer des fonctionnalités associées à la classe elle-même, plutôt qu’à des instances spécifiques de la classe.
Une classe doit spécifier au moins un membre ou une interface statique. Une classe sans membre et aucune interface statique n’est pas valide.
Les interfaces statiques sont spécifiées via un StaticAttribute associé à la classe runtime. StaticAttribute porte une référence à la référence de l’interface statique ainsi qu’aux informations de version. Détails sur le contrôle de version de classe runtime à suivre.
Bien que les interfaces statiques soient déclarées dans le cadre de la classe runtime, elles ne sont en fait pas implémentées sur les instances de classe elles-mêmes. Au lieu de cela, ils sont implémentés sur la fabrique d’activation de la classe. Détails sur les fabriques d’activation à suivre.
Activation
Les classes runtime prennent éventuellement en charge l’activation , la capacité du système à produire des instances d’une classe spécifiée. Les classes doivent implémenter au moins une interface membre pour prendre en charge l’activation.
WinRT définit trois mécanismes d’activation : activation directe (sans paramètres de constructeur), activation de fabrique (avec un ou plusieurs paramètres de constructeur) et activation de composition. Les classes non composables peuvent prendre en charge l’activation directe et/ou d’usine. Les classes composables prennent uniquement en charge l’activation composable. Détails sur la composition et l’activation composable à suivre.
Les classes qui prennent en charge l’activation directe sont activées en appelant la méthode IActivationFactory.ActivateInstance sur la fabrique d’activation de la classe. Cette méthode ne prend aucun paramètre et retourne une instance nouvellement activée de la classe runtime. Détails sur les fabriques d’activation à suivre.
Les classes qui prennent en charge l’activation de la fabrique définissent une ou plusieurs interfaces de fabrique, chacune définissant à son tour une ou plusieurs méthodes de fabrique. Ces interfaces de fabrique sont implémentées sur la fabrique d’activation de la classe.
Les méthodes de fabrique prennent un ou plusieurs in
paramètres et doivent retourner une instance nouvellement activée de la classe runtime. D’autres out
paramètres au-delà de l’instance de classe nouvellement activée ne sont pas autorisés. Les méthodes de fabrique doivent prendre un ou plusieurs paramètres : l’activation sans paramètre n’est pas autorisée. L’activation directe doit être utilisée pour l’activation sans paramètre.
Les classes qui prennent en charge l’activation directe ou d’usine sont marquées avec l’activateableAttribute. L’activateableAttribute contient des informations de version (détails sur le contrôle de version de classe runtime à suivre) ainsi qu’une référence facultative à l’interface de fabrique. Les classes peuvent être marquées avec plusieurs ActivateableAttributes, au plus une pour l’activation par défaut, plus une pour chaque interface de fabrique implémentée par la fabrique d’activation de la classe. Les classes marquées avec activateableAttribute peuvent également ne pas être marquées avec le composant ComposableAttribute. Détails sur la composition à suivre.
Composition
Les classes runtime prennent éventuellement en charge la composition: la possibilité pour plusieurs instances de classe d’être combinées dans ce qui semble être un objet unique de l’extérieur. WinRT utilise la composition comme forme d’héritage de classe runtime.
Les classes WinRT peuvent éventuellement composer une seule classe de base composée, qui à son tour peut composer une classe de base composée unique, etc. Une classe n’a pas elle-même besoin d’être composée pour composer une classe de base composable. Les classes peuvent uniquement composer avec une classe composable en tant que classe de base. Une classe composable n’est pas nécessaire pour composer une autre classe composable (autrement dit, il peut s’agir de la racine de la hiérarchie). Les graphes circulaires de composition (par exemple, A compose B, qui compose A) ne sont pas autorisés.
Au moment de l’exécution, une classe de composition est une agrégation d’objets WinRT, une pour chaque objet de la chaîne de composition. Ces objets agrégés délèguent l’identité et la durée de vie à l’objet activé à l’origine dans la chaîne de composition (appelé objet de contrôle). Chaque objet de la chaîne contient un pointeur IInspectable non délégué vers la classe qu’il compose afin d’appeler des méthodes sur des interfaces de classe de base composées, y compris les méthodes sur les interfaces protégées. Chaque objet de la chaîne a un pointeur vers la classe de contrôle pour déléguer la durée de vie et l’identité, ainsi que pour appeler des méthodes sur des interfaces substituables. Détails sur les interfaces protégées et substituables à suivre.
Prenons l’exemple que Button compose le contrôle, qui compose à son tour UIElement. Dans cet exemple, une instance de Button agrège une instance de contrôle , qui agrège à son tour une instance UIElement . Les trois objets ont une référence à l’objet Button pour contrôler la durée de vie et l’identité, ainsi que pour interroger des interfaces substituables. Chaque objet a un pointeur IInspectable vers l’objet qu’il compose (Button contient un pointeur vers Control; Le contrôle contient un pointeur vers UIElement) pour pouvoir appeler des méthodes sur des interfaces implémentées sur des classes composées, y compris les interfaces protégées.
Une classe ne peut implémenter aucune interface définie sur la classe qu’elle compose, ni aucune classe de la chaîne de composition, sauf si l’interface est marquée comme substituable dans la classe composable. Détails sur les interfaces substituables à suivre.
Une classe composable doit être marquée avec un ou plusieurs ComposableAttributes. ComposableAttribute porte une référence à l’interface de fabrique de composition, que les méthodes de fabrique sur l’interface de fabrique de composition puissent être utilisées pour contrôler l’activation d’objet ou non, ainsi que les informations de version. Détails sur les interfaces de fabrique de composition et le contrôle de version à suivre. Une classe peut être marquée avec plusieurs ComposableAttributes, une pour chaque interface de fabrique de composition implémentée par la fabrique d’activation de la classe.
La projection du langage JavaScript ne prend pas en charge la composition de classe. Par conséquent, les classes composables et les classes qui composent des classes composables doivent être marquées avec le WebHostHiddenAttribute indiquant que JavaScript ne doit pas tenter de projeter ces types.
Les tiers peuvent uniquement définir des classes qui composent d’autres classes composables. Vous ne pouvez pas définir votre propre classe racine composable.
Activation composable
Une classe composable doit définir une ou plusieurs interfaces de fabrique de composition, qui implémentent à son tour une ou plusieurs méthodes de fabrique de composition. Les interfaces de fabrique de composition sont implémentées sur la fabrique d’activation de la classe. Détails sur les fabriques d’activation à suivre.
Une interface de fabrique de composition est utilisée pour créer des instances composables de la classe. Une interface de fabrique composable déclare zéro ou plusieurs méthodes de fabrique composables qui peuvent être utilisées pour activer des instances de la classe à des fins de composition. Notez qu’il est légal d’avoir une interface de fabrique composable avec zéro méthode de fabrique. Cela implique que la classe peut être utilisée pour la composition, mais que les tiers peuvent ne pas composer directement la classe , la ou les méthodes de création d’instances sont internes uniquement.
Une classe composable déclare si les méthodes de fabrique sur une interface de fabrique de composition donnée peuvent être utilisées pour activer la classe directement en tant qu’objet de contrôle ou non. Les interfaces de fabrique composables marquées comme publiques peuvent être utilisées pour activer directement une classe en tant qu’objet de contrôle, ainsi que indirectement pour activer une classe en tant qu’objet composé. Les interfaces de fabrique composables marquées protégées peuvent uniquement être utilisées pour activer indirectement une classe en tant qu’objet composé. Les classes composables peuvent toujours être activées en tant qu’objets composés.
Une interface de fabrique de composition doit être exclusiveto
la classe runtime qu’elle est implémentée.
Comme une méthode de fabrique d’activation, une méthode de fabrique de composition doit retourner une instance de la classe composable. En outre, une méthode de fabrique de composition a deux paramètres supplémentaires : le paramètre IInspectable* [in] de contrôle et le paramètre IInspectable** [out] non délégué. Une méthode de fabrique de composition peut éventuellement avoir des paramètres supplémentaires in
. S’il est spécifié, l’ajout dans les paramètres doit se produire au début de la signature de méthode, avant que les paramètres mandatés répertoriés précédemment. Une méthode de fabrique de composition ne peut pas avoir de paramètres supplémentaires out
au-delà de la non-délégation IInspectable** et des paramètres de valeur de retour.
Lorsqu’une classe composable est activée pour la composition (par exemple, Control ou UIElement lorsqu’une instance Button est activée), un pointeur vers l’objet qui contrôle l’identité et la durée de vie est transmis via le paramètre IInspectable* [in] de contrôle. La méthode de fabrique composable retourne l’instance nouvellement activée comme valeur de retour. Cette instance délègue toutes les fonctionnalités de gestion des identités et de la durée de vie au contrôle IInspectable* fourni. En outre, la méthode de fabrique composable retourne un pointeur vers un IInspectable non délégué* que la classe de composition peut utiliser pour appeler des méthodes sur une classe composée.
Lorsqu’une classe composable est activée en tant que classe de contrôle (par exemple, Button dans l’exemple précédent), les mêmes méthodes de fabrique composables sont utilisées pour l’activation de la composition. Lors de l’activation directe d’une classe composable, la valeur Null est passée pour le paramètre *IInspectable* de contrôle. Il s’agit d’un indicateur de la classe composable qu’elle est activée en tant que classe de contrôle. Lorsqu’une classe de contrôle crée l’instance de la classe qu’elle compose, elle transmet une référence à elle-même en tant que paramètre IInspectable* de contrôle. La méthode de fabrique composable retourne l’instance de classe de contrôle comme valeur de retour. Le paramètre IInspectable** [out] non délégué est ignoré par le code client lors de l’activation d’une classe composable de contrôle.
En s’appuyant sur l’exemple Button -Control ->>UIElement précédent, la classe button serait activée en appelant l’une de ses méthodes de fabrique de composition et en passant null pour le paramètre externe. Le bouton active à son tour une instance de contrôle , en passant une référence à elle-même en tant que paramètre externe. Le contrôle active à son tour une instance UIElement , en transmettant la référence externe qu’elle a reçue en tant que paramètre externe. La méthode d’usine UIElement revient à Contrôlerl’UIElement nouvellement créé dans le paramètre d’instance, ainsi qu’une référence à la non-délégation IInspectabled’UIElement dans le paramètre interne. La méthode de fabrique de contrôle retourne à Button le contrôle nouvellement créé dans le paramètre d’instance, ainsi qu’une référence à l’IInspectable non délégué de Control dans le paramètre interne. La fabrique de composition Button retourne au code appelant le bouton nouvellement créé dans le paramètre d’instance et null pour le paramètre interne.
Il est possible qu’une classe soit parfois activée pour la composition, et d’autres fois activées comme classe de contrôle. Par exemple, si RadioButton a composé Button, button est activé pour la composition lorsqu’un RadioButton a été activé; mais activé comme classe de contrôle lorsque Button a été activé directement. Dans les deux cas, la classe Control composée par Button est activée pour la composition.
Interfaces protégées
Une classe composable peut déclarer zéro ou plusieurs de ses interfaces membres à protéger. Une classe non composable peut ne pas déclarer les interfaces membres à protéger. Seul le code d’une classe qui compose une classe composable (directement ou indirectement) peut rechercher et utiliser des interfaces déclarées par la classe composable comme protégées. Le code provenant de l’extérieur de la chaîne de composition ne peut pas interroger, ni utiliser, les interfaces déclarées par la classe composable comme protégées.
Par exemple, si UIElement déclare une interface protégée IUIElementProtected, seules les classes qui composent UIElement( y compris la composition directe (Control) et indirect (Button) peuvent rechercher et utiliser l’interface IUIElementProtected .
Interfaces substituables
Une classe composable peut déclarer zéro ou plusieurs de ses interfaces membres pour être substituables. Une interface substituable peut uniquement être interrogée et utilisée dans une chaîne de composition, similaire aux règles relatives à l’accès aux interfaces protégées détaillées précédemment. Toutefois, lorsqu’une interface protégée peut uniquement être implémentée par la classe qui l’a déclarée à l’origine, les interfaces substituables peuvent être réinsérées par les classes qui composent la classe qui a implémenté l’interface substituable.
Au moment de l’exécution, tout code de classe composable qui tire parti de l’interface substituable doit QueryInterface pour l’interface via le pointeur IInspectable* qui est utilisé pour la délégation d’identité et de durée de vie. Ce pointeur retourne l’implémentation de l’interface substituable au plus tôt dans la chaîne de composition (c’est-à-dire, plus proche de l’instance de classe de contrôle). Une classe qui souhaite accéder aux interfaces substituables de la classe qu’elle compose peut le faire via la référence non déléguée qu’une classe composable contient à sa classe composée.
Prenons l’exemple que UIElement déclare une interface substituable IUIElementOverridable. Dans ce cas, les classes qui dérivent de UIElement, y compris la dérivation directe (Control) et indirecte (Button), sont autorisées à l’implémenter. Si le code dans UIElement était nécessaire pour accéder aux fonctionnalités dans IUIElementOverridable, UIElement interroge l’IInspectable de contrôle pour obtenir la première implémentation de la chaîne de composition. Si Control et Button implémentent IUIElementOverridable, l’implémentation button est retournée lorsque l’IInspectable de contrôle a été interrogée. Si Button souhaite accéder à sa fonctionnalité de classe composée, il peut utiliser l’IInspectable non délégué retourné par la méthode de fabrique de composition pour interroger la classe de base pour cette interface.
Fabriques d'activation
Une classe runtime dispose éventuellement d’une fabrique d’activation. Une classe runtime doit avoir une fabrique d’activation si la classe est activable, composable ou a des interfaces statiques. La fabrique d’activation d’une classe peut être récupérée à partir du système au moment de l’exécution via la fonction Win32 RoGetActivationFactory .
Les fabriques d’activation doivent implémenter l’interface IActivationFactory . Toutefois, seules les classes qui prennent en charge l’activation directe fournissent une implémentation de la méthode Unique ActivateInstanced’IActivationFactory. Les classes qui ne prennent pas en charge l’activation directe doivent retourner E_NOTIMPL à partir d’IActivationFactory.ActivateInstance.
La fabrique d’activation doit implémenter toutes les interfaces de fabrique d’activation, les interfaces de fabrique de composition et les interfaces statiques définies sur la classe runtime.
Il n’existe aucune garantie que les projections de langage conservent une seule instance d’usine d’activation pour la durée de vie de la fabrique. Les auteurs de classe WinRT qui doivent enregistrer des informations de longue durée pour l’accès aux membres statiques doivent les stocker quelque part en dehors de la fabrique d’activation.
Projection basée sur des classes
Bien que WinRT soit principalement un modèle de programmation basé sur l’interface, les classes runtime fournissent un modèle de programmation basé sur une classe mieux aligné sur les langages de programmation modernes, standard et orienté objet (OO). Les projections de langage sont censées projeter une classe runtime en tant qu’entité unique, plutôt qu’en tant qu’ensemble d’interfaces que le développeur doit traiter séparément.
Pour atteindre ce modèle basé sur une classe, les projections de langage sont censées projeter des membres de type à partir des interfaces membres d’une classe en tant que membres de classe directs. Les projections de langage sont censées projeter des membres de type à partir des interfaces statiques d’une classe en tant que membres de classe statique. Enfin, les projections de langage sont censées projeter des méthodes d’activation (activation directe ainsi que des interfaces d’usine et d’interfaces de fabrique composables) en tant que constructeurs de classe.
Pour faciliter cette projection basée sur une classe, les métadonnées des classes runtime spécifient un membre de classe pour toutes les méthodes, propriétés et événements de chaque interface qu’ils implémentent. Chaque membre de classe est explicitement lié au membre d’interface où il a été défini à l’origine. Cela permet aux projections de langage d’exposer la classe en tant qu’entité unique, en gérant toutes les requêtes d’interface et le comptage de références sous les couvertures pour le compte du développeur.
Par défaut, chaque membre d’interface implémenté est projeté en tant que membre de classe. Toutefois, étant donné que les classes runtime peuvent implémenter plusieurs interfaces et versions indépendantes au fil du temps (détails de contrôle de version à suivre), il est possible qu’il y ait des collisions de noms pour les membres définis sur différentes interfaces implémentées par une classe runtime unique.
Lorsque des collisions se produisent, la projection de membre de classe par défaut est impossible. Si des collisions se produisent entre les interfaces ajoutées dans des versions distinctes, le membre en collision de la version la plus ancienne est projeté en tant que membre de classe. Lorsque des collisions se produisent entre les interfaces ajoutées dans la même version, aucun des membres en collision n’est projeté en tant que membres de classe. Notez que les méthodes avec des noms en collision sont autorisées tant que toutes les versions sont de différentes arités , comme décrit dans la surcharge des méthodes.
Les membres d’interface qui ne sont pas projetés en tant que membres de classe doivent être mis à la disposition des développeurs. En règle générale, il s’agit d’une opération effectuée par un opérateur de conversion ou de recherche dynamique, ce qui permet au développeur de spécifier l’interface et la méthode spécifiques qu’il souhaite appeler.
Pour résoudre les collisions de noms de méthode, les classes runtime peuvent spécifier d’autres noms pour les méthodes sur les interfaces membres et statiques qu’elles implémentent. Ce nom alternatif est utilisé par la projection de langage pour fournir un accès ambigu aux noms de méthode en collision à partir d’une instance de classe. Bien que la classe runtime puisse fournir un autre nom de méthode, la signature de méthode, les paramètres et tous les attributs attachés à la méthode ou à ses attributs doivent toujours correspondre exactement à la définition d’interface d’origine.
Étant donné que l’activation directe, les méthodes de fabrique et les méthodes de fabrique de composition sont projetées en tant que constructeurs de classe, elles sont toutes projetées sur la classe runtime comme s’ils ont le même nom. Toutes les méthodes de toutes les interfaces de fabrique doivent avoir des signatures uniques, doivent favoriser la surcharge basée sur une arité sur la surcharge basée sur le type et doivent utiliser DefaultOverloadAttribute pour lever l’ambiguïté des méthodes de fabrique de la même arité.
Contrôle de version de classe
Les classes runtime peuvent être de manière additive. Les versions ultérieures d’une classe runtime donnée peuvent spécifier des interfaces supplémentaires de tous les types, avec plus d’informations sur les types d’interface individuels ci-dessous. Les interfaces préexistantes spécifiées par une classe ne peuvent jamais être supprimées ou modifiées sans rompre la compatibilité descendante.
Contrôle de version de l’interface membre
Les interfaces membres sur les classes runtime peuvent être de manière additive. Les versions ultérieures d’une classe runtime donnée peuvent implémenter des interfaces membres supplémentaires, même si la classe n’avait jamais implémenté d’interfaces membres auparavant. Les versions ultérieures d’une classe runtime composable donnée peuvent implémenter des interfaces protégées et substituables supplémentaires.
Les interfaces implémentées par une classe runtime transportent éventuellement la versionAttribute pour distinguer quand des interfaces spécifiques ont été ajoutées au type de classe runtime. Les valeurs d’implémentation d’interface sans VersionAttribute sont considérées comme ayant la même valeur de version que le type de classe runtime englobant.
Contrôle de version d’interface statique
Les interfaces statiques sur les classes runtime peuvent être de manière additive. Les versions ultérieures d’une classe runtime donnée peuvent implémenter des interfaces statiques supplémentaires, même si la classe n’avait jamais implémenté d’interfaces statiques auparavant.
StaticAttribute inclut un paramètre UInt32 pour le numéro de version, qui définit la version de Windows qui a ajouté cette prise en charge de l’activation.
Contrôle de version d’activation
La prise en charge de l’activation pour les classes d’exécution est de façon additive. Les versions ultérieures d’une classe runtime donnée peuvent implémenter des mécanismes d’activation supplémentaires, même si la classe n’avait jamais implémenté un mécanisme d’activation. Notez que les classes composables ne sont pas activées et peuvent donc ne pas ajouter de prise en charge de l’activation.
Notez qu’une classe prenant en charge l’activation directe peut uniquement ajouter de nouvelles interfaces d’activation de fabrique. Classe qui n’a précédemment pris en charge que l’activation d’usine peut ajouter une prise en charge directe de l’activation ainsi que de nouvelles interfaces d’activation de fabrique.
L’activateableAttribute inclut un paramètre UInt32 pour le numéro de version. Le numéro de version de l’ActivateableAttribute définit la version de Windows qui a ajouté cette prise en charge de l’activation.
Contrôle de version de composition
La prise en charge de la composition pour les classes d’exécution est modifiable de manière additive. Les versions ultérieures d’une classe runtime composable donnée peuvent implémenter des mécanismes de composition supplémentaires, à condition que la classe ait été définie comme composable lors de sa création. Les classes composables peuvent ne pas ajouter de prise en charge de l’activation.
Le composant ComposableAttribute inclut un paramètre UInt32 pour le numéro de version. Le numéro de version de ComposableAttribute définit la version de Windows qui a ajouté cette prise en charge de composition.
Attributs personnalisés
WinRT prend en charge la définition des attributs de métadonnées personnalisés. Toutes les constructions du système de type WinRT peuvent porter des attributs de métadonnées personnalisés. Cela inclut tous les types nommés (énumérations, structs, délégués, interfaces, classes, etc.) ainsi que les éléments individuels contenus dans les constructions de type (telles que les méthodes, les paramètres, etc.).
Les attributs personnalisés sont nommés comme d’autres types WinRT. Toutefois, ils ne peuvent pas être activés. Elles sont purement une construction de données.
Les attributs personnalisés définissent un schéma de données de paramètres positionnels ou de champs nommés. Un attribut personnalisé peut ne pas utiliser à la fois des paramètres positionnels et des champs nommés, il doit choisir l’un ou l’autre. Les types de paramètres et de champs d’un attribut personnalisé sont limités aux types fondamentaux WinRT, aux énumérations et aux références à d’autres types WinRT. Aucun autre paramètre ou type de champ n’est autorisé.
Les attributs personnalisés qui utilisent des paramètres positionnels doivent définir un ou plusieurs ensembles valides de paramètres positionnels. Chaque ensemble doit spécifier zéro ou plusieurs paramètres positionnels. Une instance de l’attribut personnalisé doit spécifier un ensemble unique de paramètres positionnels ainsi que des données pour chaque paramètre positionnel dans le jeu sélectionné.
Un attribut personnalisé qui utilise des champs nommés spécifie zéro champs avec des noms et des types. Une instance de l’attribut personnalisé doit spécifier les paires nom/valeur pour les champs qu’il souhaite spécifier. Une instance peut spécifier des valeurs pour tous, certains ou aucun des paires nom/valeur.
Il est valide pour qu’un attribut n’ait ni paramètres positionnels ni champs nommés.
Un attribut personnalisé doit avoir une visibilité publique.
Un attribut peut spécifier les types de constructions de type WinRT qu’il peut être associé via AttributeUsageAttribute.
Les tiers ne peuvent pas définir d’attributs personnalisés. Seuls les attributs personnalisés définis par le système sont pris en charge.