Cet article a fait l'objet d'une traduction automatique.

Windows Runtime et le CLR

Les rouages du système avec .NET et Windows Runtime

Shawn Farkas

 

Le Windows Runtime (WinRT) propose un large éventail de nouvelles API pour les développeurs Windows Experience. 4.5 Le CLR, les navires dans le cadre du Microsoft .NET Framework 4.5 dans Windows 8, permet aux développeurs écrivant géré code afin d'utiliser les API de façon naturelle, comme si elles étaient une autre bibliothèque de classes. Vous pouvez ajouter une référence au fichier de métadonnées Windows (WinMD) qui définit l'API que vous souhaitez appeler, puis appeler dedans comme avec une API managée standard. Visual Studio ajoute automatiquement une référence à l'intégré WinRT APIs aux nouveaux projets d'interface utilisateur de Windows, afin que votre application peut simplement commencer à utiliser cette nouvelle API défini.

Sous le capot, le Common Language Runtime fournit l'infrastructure pour le code managé consommer les fichiers WinMD et transition entre du code managé et l'exécution de Windows. Dans cet article, je vais montrer certains de ces détails. Vous allez repartir avec une meilleure compréhension de ce qui se passe en arrière-plan lorsque votre programme managé appelle une API WinRT.

Beaucoup de fichiers WinMD à partir de Code managé

WinRT APIs sont définis dans les fichiers WinMD sont codés en utilisant le format de fichier décrit dans ECMA-335 (bit.ly/sLILI). Bien que WinMD fichiers et assemblys .NET Framework partagent un encodage commun, ils ne sont pas les mêmes. Une des différences principales dans les métadonnées découle du fait que le système de type WinRT est indépendant du système de type .NET.

Des programmes tels que le compilateur c# et de Visual Studio utilisent des métadonnées CLR API (par exemple IMetaDataImport) pour lire les métadonnées de l'assembly .NET Framework et peuvent désormais lire des métadonnées de fichiers WinMD ainsi. Parce que les métadonnées ne sont pas exactement identique à un assembly .NET, le lecteur de métadonnées CLR insère un adaptateur entre les API de métadonnées et le fichier WinMD en cours de lecture. Cela permet de WinMD les fichiers à lire comme si elles étaient des assemblys .NET (voir Figure 1).

The CLR Inserts a Metadata Adapter Between WinMD Files and the Public Metadata Interface
Figure 1 le CLR insère un adaptateur de métadonnées entre les fichiers WinMD et l'Interface de métadonnées Public

Exécuter ILDasm vous aide à comprendre les modifications que l'adaptateur de métadonnées CLR exécute sur un fichier WinMD. Par défaut, ILDasm affiche le contenu d'un fichier WinMD dans sa forme brute, comme il est codé sur disque sans l'adaptateur de métadonnées CLR. Toutefois, si vous passez le paramètre de ligne de commande /project à ILDasm, il permet à l'adaptateur de métadonnées et vous pouvez consulter les métadonnées comme le CLR et outils managés liront.

En exécutant des copies de ILDasm côte à côte, avec et sans le paramètre /project — vous pourrez facilement explorer les modifications apportées par l'adaptateur de métadonnées CLR à un fichier WinMD.

Le Runtime Windows et les systèmes de Type .NET

D'entre les grandes opérations effectue l'adaptateur de métadonnées est de fusionner les systèmes de type WinRT et .NET. Un haut niveau, cinq différentes catégories de types WinRT peuvent apparaître dans un fichier WinMD et devront être examinées par le CLR. Celles-ci sont listées à la figure 2. Examinons plus en détail chacune des catégories.

Figure 2 Types de WinRT pour un fichier WinMD

Category Exemples
Types de WinRT standard Windows.Foundation.Collections.PropertySet, Windows.Networking.Sockets.DatagramSocket
Types primitifs Byte, Int32, String, Object
Types projetés Windows.Foundation.Uri, Windows.Foundation.DateTime
Interfaces projetées Windows.Foundation.Collections.IVector <T>, Windows.Foundation.Iclosable
Types avec assistants .NET Windows.Storage.Streams.IInputStream, Windows.Foundation.IasyncInfo

Types de WinRT standard alors que le CLR a prise en charge spéciale pour de nombreuses catégories de types exposés par l'exécution de Windows, la plupart des types de WinRT n'est pas traitée du tout spécialement par le CLR. Au lieu de cela, ces types s'affichent pour les développeurs .NET non modifiés, et ils peuvent servir comme une bibliothèque de grande classe pour permettre l'écriture magasin Windows applications.

Types primitifs cet ensemble de types primitifs est codé dans un fichier WinMD à l'aide de l'énumération ELEMENT_TYPE même cette utilisation d'assemblys .NET. Le Common Language Runtime interprète automatiquement ces types primitifs comme s'ils étaient les équivalents .NET.

Pour l'essentiel, traitant WinRT types primitifs comme des types primitifs .NET tout fonctionne. Par exemple, un entier de 32 bits présente le même modèle de bit dans le Runtime Windows comme elle le fait dans .NET, le Common Language Runtime peut traiter un WinRT DWORD comme un System.Int32 .NET sans aucune difficulté. Mais deux exceptions notables sont des objets et des chaînes.

Dans l'exécution de Windows, les chaînes sont représentées avec le type de données HSTRING, qui n'est pas identique à un System.String .NET. De même, ELEMENT_TYPE_OBJECT signifie System.Object à .NET, même si cela signifie IInspectable * à l'exécution de Windows. Pour des chaînes et des objets, le Common Language Runtime doit marshaler des objets en cours d'exécution pour effectuer des conversions entre des types de représentations WinRT et .NET. Vous verrez comment ce marshaling fonctionne plus loin dans cet article.

Projeté Types il existe certains types .NET fondamentaux existants qui possèdent des équivalents dans le système de type WinRT. Par exemple, le Runtime Windows définit une structure TimeSpan et une classe Uri, qui ont tous deux types correspondants dans le .NET Framework.

Pour éviter d'obliger les développeurs .NET pour convertir dans les deux sens entre ces types de données fondamentaux, le CLR projette la version WinRT en son équivalent .NET. Ces projections sont effectivement fusionner les points que le Common Language Runtime insère entre .NET et WinRT systèmes de type.

Par exemple, la Syndication de Runtime Windows­Client.RetrieveFeedAsync API prend un WinRT Uri comme son paramètre. Au lieu de demander aux développeurs .NET de créer manuellement une nouvelle instance de Windows.Foundation.Uri à passer à cette API, les projets CLR le type comme un System.Uri, qui permet aux développeurs .NET utilisent le type ils sont plus familiers avec.

Un autre exemple d'une projection est le Windows.Founda­tion.Structure HResult qui est projetée par le Common Language Runtime pour le type System.Exception. Dans .NET, les développeurs sont habitués à voir des informations d'erreur transmises comme une exception plutôt que comme un échec HRESULT, afin d'avoir une API WinRT tels que IAsycn­Info.ErrorCode express informations relatives aux erreurs comme une structure HResult ne se sentent pas naturelle. Au lieu de cela, le Common Language Runtime projets HResult vers l'Exception, ce qui en fait une API WinRT comme IAsyncInfo.ErrorCode plus utilisable pour les développeurs .NET. Voici un exemple de la propriété IAsyncInfo ErrorCode codé dans Windows.winmd :

.class interface public windowsruntime IAsyncInfo
{
  .method public abstract virtual
    instance valuetype Windows.Foundation.HResult
    get_ErrorCode()
}

Et Voici la propriété ErrorCode de IAsyncInfo après la projection du CLR :

 

.class interface public windowsruntime IAsyncInfo
{
 .method public abstract virtual
   instance class [System.Runtime]System.Exception
   get_ErrorCode()
}

Projetée des Interfaces The Windows Runtime fournit également un ensemble d'interfaces fondamentales qui possèdent des équivalents .NET. Le Common Language Runtime effectue les projections type sur ces interfaces, ainsi fusionner à nouveau les systèmes de type à ces points fondamentaux.

Les exemples les plus courants des interfaces projetées sont les interfaces de collection WinRT, tels que IVector <T>, IIterable <T> et IMap < K, V >. Les développeurs qui utilisent .NET sont familiers avec les interfaces de collection telles que IList <T>, IEnumerable <T> et IDictionary < K, V >. Les projets CLR la WinRT collection interface .NET correspondants et cache aussi le WinRT interfaces afin que les développeurs n'aient à faire face à deux ensembles fonctionnellement équivalents de types qui font la même chose.

En plus de projeter ces types quand ils apparaissent sous forme de paramètres et types de retour de méthodes, le Common Language Runtime doit également projet ces interfaces lorsqu'ils apparaissent dans la liste de mise en oeuvre l'interface d'un type. Par exemple, le type WinRT PropertySet implémente le WinRT IMap < string, object > interface. Le Common Language Runtime, cependant, projettera PropertySet comme un type qui implémente IDictionary < string, object >. Lorsque vous effectuez cette projection, des membres de PropertySet qui servent à mettre en œuvre IMap < string, object > sont masqués. Au lieu de cela, les développeurs .NET accèdent PropertySet via correspondant IDictionary < string, object > Méthodes. Voici une vue partielle de PropertySet conformément au codage dans Windows.winmd :

.class public windowsruntime PropertySet
  implements IPropertySet,
    class IMap`2<string,object>,
    class IIterable`1<class IKeyValuePair`2<string,object> >
{
  .method public instance uint32 get_Size()
  {
    .override  method instance uint32 class 
      IMap`2<string,object>::get_Size()
  }
}

Et Voici une vue partielle de PropertySet après la projection du CLR :

.class public windowsruntime PropertySet
  implements IPropertySet,
    class IDictionary`2<string,object>,
    class IEnumerable`1<class KeyValuePair`2<string,object> >
{
  .method private instance uint32 get_Size()
  {
  }
}

Notez que les projections de type trois se produisent : IMap < string, object > IDictionary < string, object >, IKeyValuePair < string, object > KeyValuePair < string, object > et IIterable <IKeyValuePair> IEnumerable <KeyValuePair>. Notez également que la méthode obtenue d'IMap est masquée.

Types avec .NET Framework Helpers The Windows Runtime possède plusieurs types qui n'ont pas une fusion complète point dans le système de type .NET, mais sont assez importantes pour la plupart des applications que le .NET Framework fournit les méthodes d'assistance pour travailler avec eux. Deux des meilleurs exemples sont les interfaces de flux et async WinRT.

Bien que le CLR saillie Windows.Storage.Streams.IRandomAccess­Stream à System.Stream, elle fournit un ensemble de méthodes d'extension pour IRandom­AccessStream qui permet à votre code traiter ces flux WinRT comme s'ils étaient des flux .NET. Par exemple, vous pouvez facilement lire un flux WinRT avec StreamReader .NET en appelant la méthode d'extension OpenStreamForReadAsync.

Le Runtime Windows fournit un ensemble d'interfaces qui représentent des opérations asynchrones, telles que l'interface IAsyncInfo. Dans le .NET Framework 4.5, il y a prise en charge intégrée dans l'attente des opérations asynchrones, que les développeurs veulent utiliser avec WinRT APIs dans la même façon que pour les API .NET.

Pour ce faire, le .NET Framework est livré avec un ensemble de méthodes d'extension GetAwaiter pour les interfaces d'async WinRT. Ces méthodes sont utilisées par les compilateurs c# et Visual Basic pour activer les opérations asynchrones en attente WinRT. Voici un exemple :

private async Task<string> ReadFilesync(StorageFolder parentFolder, 
  string fileName)
{
  using (Stream stream = await parentFolder.OpenStreamForReadAsync(fileName))
  using (StreamReader reader = new StreamReader(stream))
  {
    return await reader.ReadToEndAsync();
    }
}

Transition entre le .NET Framework et Windows Runtime The CLR fournit un mécanisme pour le code managé d'appeler en toute transparence WinRT APIs et pour l'exécution de Windows effectuer un rappel dans du code managé.

À son niveau le plus bas, le Runtime Windows est construit au-dessus des concepts COM, n'est pas surprenant que la prise en charge CLR appelant WinRT APIs est construit sur infrastructure existante de COM interop.

Une différence importante entre WinRT interop et COM interop est combien moins de configuration, vous avez à traiter dans l'exécution de Windows. WinMD fichiers des métadonnées riches décrivant toutes les API qu'ils êtes exposant avec une cartographie bien définie pour le système de type .NET, donc il n'y a pas besoin d'utiliser tous les attributs MarshalAs dans du code managé. De même, parce que Windows 8 est fourni avec les fichiers WinMD pour ses APIs WinRT, vous n'avez pas besoin d'avoir un assembly PIA empaqueté avec votre application. Au lieu de cela, le CLR utilise les fichiers de WinMD dans la boîte pour découvrir tout ce qu'il a besoin de savoir sur la façon d'appeler WinRT APIs.

Ces fichiers WinMD fournissent les définitions de types managés qui sont utilisées pour permettre aux développeurs managés accès à l'exécution de Windows en cours d'exécution. Bien que l'API que le Common Language Runtime lit à partir d'un fichier WinMD contient la définition d'une méthode qui est formatée pour être facilement utilisé à partir du code managé, l'API WinRT sous-jacente utilise une signature API différente (parfois dénommé l'interface binaire d'application, ou ABI, signature). Un exemple d'une différence entre les signatures API et ABI est que, comme COM standard, WinRT APIs retournent des valeurs HRESULT, et la valeur de retour d'une API WinRT est en fait un paramètre de sortie dans la signature de l'ABI. Je vais montrer un exemple de comment une signature de méthode managée est transformée en une signature WinRT ABI quand je vois comment le Common Language Runtime appelle une API WinRT ultérieurement dans cet article.

Wrappers pouvant être appelés par le runtime et les Wrappers pouvant être appelés par COM

Lorsqu'un objet WinRT entre dans le Common Language Runtime, il doit pouvoir être appelée comme s'il s'agissait d'un objet .NET. Pour ce faire, le CLR encapsule chaque objet WinRT dans un wrapper pouvant être appelé par le runtime (RCW). Le RCW est ce que le code managé interagit avec et est l'interface entre votre code et l'objet WinRT qui est à l'aide de votre code.

A l'inverse, lorsqu'on utilise des objets managés du runtime Windows, ils doivent être appelés comme s'ils étaient des objets WinRT. Dans ce cas, les objets managés sont enveloppés dans un wrapper pouvant être appelé par COM (CCW) lorsqu'ils sont envoyés à l'exécution de Windows. Étant donné que le Runtime Windows utilise la même infrastructure que COM, il peut interagir avec CCWs aux fonctionnalités d'accès sur l'objet managé (voir Figure 3).

Using Wrappers for Windows Runtime and Managed Objects
La figure 3 pour Windows Runtime et des objets managés à l'aide de Wrappers

Marshaling de Stubs

Lorsque le code managé des transitions de traverser une frontière d'interopérabilité, y compris les limites WinRT, plusieurs choses doivent se produire :

  1. Convertir des paramètres d'entrée managés équivalents WinRT, y compris la construction des wrappers com pour des objets managés.
  2. Trouver l'interface qui implémente la méthode WinRT est appelée depuis que la méthode est appelée sur le RCW.
  3. Appeler la méthode WinRT.
  4. Convertir les paramètres de sortie WinRT (y compris les valeurs de retour) en équivalents managés.
  5. Convertir les valeurs HRESULT d'échec de l'API WinRT en une exception managée.

Ces opérations ont lieu dans un talon de marshaling, le Common Language Runtime génère au nom de votre programme. Les stubs de marshaling sur un RCW sont ce que le code managé appelle en fait avant de passer en une API WinRT. De même, les appels Windows Runtime dans les stubs de marshaling CLR générés sur un CCW lorsqu'elle effectue la transition du code managé.

Le pont qui enjambe le fossé entre le Runtime Windows et .NET Framework fournissent des stubs de marshaling. Compréhension de leur fonctionnement vous aidera à mieux comprendre ce qui se produit lorsque votre programme appelle dans l'exécution de Windows.

Un appel exemple

Imaginez une API WinRT qui prend une liste de chaînes et les concatène, avec une chaîne de séparateur entre chaque élément. Cette API peut avoir une signature managée telles que :

public string Join(IEnumerable<string> list, string separator)

Le Common Language Runtime doit appeler la méthode telle qu'elle est définie dans le ABI, donc il a besoin de comprendre la signature ABI de la méthode. Heureusement, un ensemble de transformations déterministes peut être appliqué pour obtenir sans ambiguïté une signature ABI donnée une signature API. La première transformation est de remplacer les types de données projetées avec leurs équivalents WinRT, qui retourne l'API à la forme dans laquelle elle est définie dans le fichier WinMD avant le chargement de la carte de métadonnées il. Dans ce cas, IEnumerable <T> est en fait une projection de IIterable <T>, la WinMD de cette fonction est en fait :

public string Join(IIterable<string> list, string separator)

WinRT chaînes sont stockées dans un type de données HSTRING, donc pour l'exécution de Windows, cette fonction en fait ressemble à :

public HSTRING Join(IIterable<HSTRING> list, HSTRING separator)

À la couche ABI, où l'appel se produit effectivement, WinRT APIs possède les valeurs de retour HRESULT, et la valeur de retour de leur signature est un paramètre de sortie. En outre, les objets sont des pointeurs, donc la signature ABI pour cette méthode serait :

HRESULT Join(__in IIterable<HSTRING>* list, HSTRING separator, __out HSTRING* retval)

Toutes les méthodes WinRT doivent faire partie d'une interface qui implémente un objet. Notre méthode de jointure, par exemple, pourrait faire partie d'une interface IConcatenation pris en charge par une classe StringUtilities. Avant de formuler une méthode remettent en jointure, le Common Language Runtime doit mettre la main sur le pointeur d'interface IConcatenation pour effectuer l'appel sur.

L'emploi d'un stub de marshaling est de convertir de l'original géré par appel sur un RCW à l'appel de WinRT final sur une interface WinRT. Dans ce cas, le pseudocode pour le stub de marshaling pourrait ressembler Figure 4 (avec nettoyage appels omis par souci de clarté).

Figure 4 exemple de portail Marshaling pour faire un appel depuis le CLR à l'exécution de Windows

public string Join(IEnumerable<string> list, string separator)
{
  // Convert the managed parameters to WinRT types
  CCW ccwList = GetCCW(list);
  IIterable<HSTRING>* pCcwIterable = ccwList.QueryInterface(IID_IIterable_HSTRING);
  HSTRING hstringSeparator = StringToHString(separator);
  // The object that managed code calls is actually an RCW
  RCW rcw = this;
  // You need to find the WinRT interface pointer for IConcatenation
  // implemented by the RCW in order to call its Join method
  IConcatination* pConcat = null;
  HRESULT hrQI = rcw.QueryInterface(IID_ IConcatenation, out pConcat);
  if (FAILED(hrQI))
    {
      // Most frequently this is an InvalidCastException due to the WinRT
      // object returning E_NOINTERFACE for the interface that contains
      // the method you're trying to call
      Exception qiError = GetExceptionForHR(hrQI);
      throw qiError;
    }
    // Call the real Join method
    HSTRING returnValue;
    HRESULT hrCall = pConcat->Join(pCcwIterable, hstringSeparator, &returnValue);
    // If the WinRT method fails, convert that failure to an exception
    if (FAILED(hrCall))
    {
      Exception callError = GetExceptionForHR(hrCall);
      throw callError;
    }
    // Convert the output parameters from WinRT types to .NET types
    return HStringToString(returnValue);
}

Dans cet exemple, la première étape consiste à convertir les paramètres gérés de leur représentation managée à leur représentation WinRT. Dans ce cas, le code crée un wrapper CCW pour le paramètre list et convertit le paramètre System.String à un HSTRING.

La prochaine étape est de trouver l'interface WinRT qui fournit l'implémentation de jointure. Cela se produit par l'émission d'un appel QueryInterface de l'objet WinRT est encapsulée par le wrapper RCW qui l'appelle du code managé se joindre sur. La raison la plus courante qu'une exception InvalidCastException est levée retournée par un appel de méthode WinRT est si cet appel QueryInterface échoue. Cela peut se produire l'une des raisons sont que l'objet WinRT n'implémente pas toutes les interfaces qui attendais à l'appelant.

Maintenant l'action réelle se produit, le stub d'interopérabilité lance l'appel réel à la méthode WinRT Join, qui fournit un emplacement pour stocker la logique pour retourner la valeur HSTRING. Si la méthode WinRT échoue, il l'indique en affichant un échec HRESULT, qui le stub d'interopérabilité convertit en une Exception et la lève. Cela signifie que si votre code managé voit une exception levée par un appel de méthode WinRT, il est probable que la méthode WinRT est appelée retourné un échec HRESULT et le CLR a levé une exception pour indiquer cet état Échec à votre code.

La dernière étape consiste à convertir les paramètres de sortie de leur représentation WinRT à leur forme .NET. Dans cet exemple, la logique retour valeur est un paramètre de sortie de l'appel de Join et doit être converti en une chaîne .NET depuis un HSTRING. Cette valeur peut ensuite être retournée comme résultat du stub.

L'appel de l'exécution de Windows dans le Code managé

Les appels qui proviennent de l'exécution de Windows et la cible géré code travail d'une manière similaire. Le Common Language Runtime répond à des appels QueryInterface que le composant d'exécution de Windows effectue contre elle avec une interface qui possède une table de fonctions virtuelles qui est remplie avec les méthodes stub d'interopérabilité. Ces talons remplissent la même fonction que celle que j'ai montré précédemment, mais en sens inverse.

Prenons encore une fois, le cas de l'API de rejoindre sauf cette fois assumer il est implémenté dans le code managé et est appelé dans d'un composant d'exécution de Windows. Pseudo-code pour un stub qui permet cette transition se produit peut ressembler Figure 5.

Figure 5 exemple de portail Marshaling pour effectuer un appel depuis le Runtime Windows au CLR

HRESULT Join(__in IIterable<HSTRING>* list, 
  HSTRING separator, __out HSTRING* retval)
{
  *retval = null;
  // The object that native code is calling is actually a CCW
  CCW ccw = GetCCWFromComPointer(this);
  // Convert the WinRT parameters to managed types
  RCW rcwList = GetRCW(list);
  IEnumerable<string> managedList = (IEnumerable<string>)rcwList;
  string managedSeparator = HStringToString(separator);
  string result;
  try
  {
    // Call the managed Join implementation
    result = ccw.Join(managedList, managedSeparator);
  }
  catch (Exception e)
  {
    // The managed implementation threw an exception -
    // return that as a failure HRESULT
    return GetHRForException(e);
  }
  // Convert the output value from a managed type to a WinRT type
  *retval = StringToHSTring(result);
  return S_OK;
}

Tout d'abord, ce code convertit les paramètres d'entrée de leurs types de données WinRT dans les types managés. En supposant que la liste d'entrée est un objet WinRT, le talon doit obtenir un wrapper RCW pour représenter cet objet pour permettre à du code managé à l'utiliser. La valeur de chaîne est simplement convertie un HSTRING à un System.String.

Ensuite, l'appel est effectué dans l'implémentation managée de la méthode Join sur la CCW. Si cette méthode lève une exception, le stub d'interopérabilité l'attrape et la convertit en un échec HRESULT retourné à l'appelant de WinRT. C'est ce qui explique pourquoi certaines exceptions levées à partir du code managé appelé par les composants d'exécution Windows ne tombe en panne le processus. Si le composant d'exécution Windows gère la valeur HRESULT d'échec, c'est effectivement identique à attraper et manipuler la levée d'une exception.

La dernière étape consiste à convertir le paramètre de sortie de son type de données .NET pour le type de données équivalent WinRT, dans ce cas convertir la System.String à un HSTRING. La valeur de retour est ensuite placée dans le paramètre de sortie et un succès que HRESULT est retournée.

Interfaces projetées

Je l'ai mentionné plus tôt, que le Common Language Runtime projettera certaines interfaces WinRT en interfaces .NET équivalentes. Par exemple, IMap < K, V > est projeté à IDictionary < K, V >. Cela signifie que n'importe quelle carte WinRT est accessible sous forme d'un dictionnaire .NET et vice versa. Pour activer cette projection de travailler, un autre jeu de stubs est nécessaire pour implémenter l'interface WinRT en ce qui concerne l'interface .NET qu'il est projeté à et vice versa. Par exemple, IDictionary < K, V > a une méthode TryGetValue, mais IMap < K, V > ne contient pas cette méthode. Pour autoriser des appelants managés d'utiliser TryGetValue, le Common Language Runtime fournit un stub qui met en œuvre cette méthode en ce qui concerne les méthodes que IMap n'a pas. Cela ressemblera à Figure 6.

Figure 6 implémentation conceptuelle de IDictionary en termes d'IMap

bool TryGetValue(K key, out V value)
{
  // "this" is the IMap RCW
  IMap<K,V> rcw = this;
  // IMap provides a HasKey and Lookup function, so you can
  // implement TryGetValue in terms of those functions
  if (!rcw.HasKey(key))
    return false;
  value = rcw.Lookup(key);
  return true;
}

Notez que, pour faire son travail, ce portail de conversion effectue plusieurs appels à l'implémentation sous-jacente d'IMap. Par exemple, supposons que vous avez écrit le bit suivant du code managé pour voir si un objet Windows.Foundation.Collections.PropertySet contient la clé « Boubacar » :

 

object value;
if (propertySet.TryGetValue("NYJ", out value))
{
  // ...
}

Comme l'appel TryGetValue détermine si le jeu de propriétés contient les clés, la pile des appels peut ressembler Figure 7.

Pile des appels pour Call TryGetValue figure 7

Stack Description
PropertySet::HasKey WinRT PropertySet mise en œuvre
HasKey_Stub Marshaling de stub de conversion appel HasKey du stub dictionnaire dans un appel WinRT
TryGetValue_Stub Talon implémentant IDictionary en termes d'IMap
système d'exploitation Managed code d'application appelle PropertySet.TryGetValue

Pour résumer

La prise en charge CLR pour l'exécution de Windows permet aux développeurs managés appeler l'API WinRT définies dans les fichiers de WinMD aussi facilement qu'ils peuvent appeler des API managées définies dans un assembly .NET standard. Sous le capot, le CLR utilise un adaptateur de métadonnées pour effectuer des projections qui aident à fusionner le système de type WinRT avec le système de type .NET. Il utilise également un ensemble des stubs d'interopérabilité pour permettre au code .NET appeler les méthodes WinRT et vice versa. Pris ensemble, ces techniques permettent aux développeurs managés appeler WinRT APIs de leurs applications Windows Store.

Shawn Farkas CLR a travaillé pendant 10 ans et est actuellement responsable du développement chargé de projection CLR Windows Runtime et .NET interop. Avant Microsoft .NET Framework 4.5, il a travaillé sur le modèle de sécurité CLR. Vous trouverez son blog à blogs.msdn.com/shawnfa.

Merci aux experts techniques suivants d'avoir relu cet article : Ryan Byington, Layla Driscoll et Yi Zhang