Condividi tramite


Il presente articolo è stato tradotto automaticamente.

Windows Runtime e CLR

Descrizione dettagliata dell'utilizzo congiunto di .NET e Windows Runtime

Shawn Farkas

 

Windows Runtime (WinRT) fornisce un'ampia serie di nuove API per gli sviluppatori Windows Experience. Il CLR 4.5, quali navi come parte del Microsoft .NET Framework 4.5 in Windows 8, consente agli sviluppatori di scrivere codice gestito per utilizzare le API in modo naturale, proprio come se fossero un'altra libreria di classi. È possibile aggiungere un riferimento al file di metadati di Windows (WinMD) che definisce le API che si desidera chiamare e quindi in loro come con una standard API gestita. Visual Studio aggiunge automaticamente un riferimento a incorporati set WinRT APIs per nuovi progetti di interfaccia utente di Windows, quindi l'applicazione può iniziare semplicemente utilizzando questa nuova API.

Sotto il cofano, Common Language Runtime fornisce l'infrastruttura per il codice gestito consumare i file WinMD e transizione tra codice gestito e il Runtime di Windows. In questo articolo vi mostrerò alcuni di questi dettagli. Verrai via con una migliore comprensione di ciò che avviene dietro le quinte quando il vostro programma gestito chiama un'API WinRT.

Utilizzo di file WinMD dal codice gestito

WinRT APIs sono definiti nel file WinMD, che sono codificati utilizzando il formato di file descritto in ECMA-335 (bit.ly/sLILI). Anche se i file WinMD e .NET Framework assembly condividono una codifica comune, non sono lo stesso. Una delle principali differenze nei metadati deriva dal fatto che il sistema di tipo WinRT è indipendente del sistema di tipo .NET.

Programmi quali il compilatore c# e Visual Studio utilizzano i metadati CLR API (ad esempio IMetaDataImport) per leggere i metadati dell'assembly Framework .NET e ora possono leggere i metadati dai file WinMD pure. Poiché i metadati non sono esattamente lo stesso come assembly .NET, il lettore di metadati CLR inserisce un adattatore tra le API dei metadati e il file di WinMD in lettura. In questo modo i file WinMD da leggere come se fossero gli assembly .NET (vedere Figura 1).

The CLR Inserts a Metadata Adapter Between WinMD Files and the Public Metadata Interface
Figura 1 Common Language Runtime inserisce una scheda metadati tra i file WinMD e l'interfaccia pubblica di metadati

Eseguire ILDasm ti aiuta a capire le modifiche che l'adattatore di metadati CLR esegue un file WinMD. Per impostazione predefinita, ILDasm illustrato il contenuto di un file WinMD nella sua forma cruda, come è codificato su disco senza l'adattatore di metadati CLR. Tuttavia, se il parametro della riga di comando /project passare ILDasm, esso consente alla scheda di metadati ed è possibile vedere i metadati come CLR e strumenti gestiti la leggerà.

Eseguendo copie di ILDasm fianco a fianco, uno con il parametro /project ed uno senza — consente di esplorare facilmente le modifiche apportate a un file WinMD dell'adattatore di metadati CLR.

Il Runtime di Windows e sistemi di tipo .NET

Una delle principali operazioni che esegue la scheda metadati è di unire i sistemi di tipo WinRT e .NET. Ad alto livello, cinque diverse categorie di tipi di WinRT possono apparire in un file WinMD e devono essere considerati da CLR. L'elenco è riportato nella Figura 2. Diamo un'occhiata a ogni categoria in modo più dettagliato.

Figura 2 tipi di WinRT per un File WinMD

Category Esempi
Tipi standard di WinRT Windows.Foundation.Collections.PropertySet, Windows.Networking.Sockets.DatagramSocket
Tipi primitivi Byte, Int32, String, Object
Tipi di proiezioni Windows.Foundation.Uri, Windows.Foundation.DateTime
Interfacce proiettate Windows.Foundation.Collections.IVector <T>, Windows.Foundation.Iclosable
Tipi con aiutanti .NET Windows.Storage.Streams.IInputStream, Windows.Foundation.IasyncInfo

Tipi standard di WinRT mentre il CLR ha un supporto speciale per molte categorie di tipi esposti dal Runtime di Windows, la maggior parte dei tipi di WinRT non è trattata appositamente da CLR. Invece, questi tipi sembrano gli sviluppatori .NET non modificati, e può essere utilizzati come libreria di grande classe per consentire la scrittura di Windows Store applicazioni.

Tipi primitivi questo insieme di tipi primitivi è codificato in un file di WinMD utilizzando l'enumerazione ELEMENT_TYPE stesso che utilizzano gli assembly di .NET. CLR interpreta automaticamente questi tipi primitivi come se fossero equivalenti, il .NET.

Per la maggior parte, trattando WinRT tipi primitivi come tipi primitivi .NET appena funziona. Per esempio, un intero a 32 bit ha lo stesso schema di bit del runtime di Windows come lo fa in .NET, CLR può trattare un DWORD WinRT come un System. Int32 .NET senza alcuna difficoltà. Ma due notevoli eccezioni sono stringhe e oggetti.

Nel Runtime di Windows, stringhe sono rappresentati con il tipo di dati HSTRING, che non è la stessa come System. String .NET. Analogamente, ELEMENT_TYPE_OBJECT significa System. Object a .NET, mentre vuol dire IInspectable * al Runtime di Windows. Per le stringhe e oggetti, CLR deve eseguire il marshalling di oggetti in fase di esecuzione per la conversione tra le rappresentazioni dei tipi di WinRT e .NET. Vedrai come questo marshalling funziona più avanti in questo articolo.

Proiettato tipi ci sono alcuni tipi di .NET fondamentali esistenti che hanno gli equivalenti nel sistema di tipo WinRT. Ad esempio, il Runtime di Windows definisce una struttura TimeSpan e una classe Uri, i quali hanno tipi corrispondenti in ambito .NET.

Per evitare di costringere gli sviluppatori .NET per convertire in avanti e indietro tra questi tipi di dati fondamentali, CLR progetti la versione WinRT equivalente .NET. Queste proiezioni sono effettivamente unire punti che Common Language Runtime inserisce tra i .NET e WinRT tipo sistemi.

Ad esempio, la Syndication di Runtime di Windows­Client.RetrieveFeedAsync API richiede un WinRT Uri come relativo parametro. Anziché richiedere agli sviluppatori .NET creare manualmente una nuova istanza di Windows.Foundation.Uri per passare questa API, i progetti CLR tipo come un URI, che consente agli sviluppatori .NET di utilizzare il tipo che ha più familiarità con.

Un altro esempio di una proiezione è il Windows.Founda­zione.HResult struttura, che è proiettata da CLR per il tipo System. Exception. In .NET, gli sviluppatori sono abituati a vedere informazioni sull'errore trasportati come un'eccezione piuttosto che come un HRESULT di errore, quindi, avendo una API WinRT come IAsycn­Info.ErrorCode esprimere informazioni sull'errore come una struttura di HResult non sente naturale. Invece, il CLR progetti HResult all'eccezione, che rende più utilizzabile una API WinRT come IAsyncInfo.ErrorCode per gli sviluppatori .NET. Ecco un esempio della proprietà IAsyncInfo ErrorCode codificato in Windows.winmd:

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

Ed ecco la proprietà IAsyncInfo ErrorCode dopo la proiezione di CLR:

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

Proiettate le interfacce il Windows Runtime fornisce anche un set di interfacce fondamentali che hanno gli equivalenti .NET. CLR esegue tipo proiezioni su queste interfacce, unire nuovamente i sistemi di tipo a questi punti fondamentali.

Gli esempi più comuni di interfacce proiettate sono le interfacce di raccolta WinRT, come Metodo IVector <T>, IIterable <T> e IMap < K, V >. Gli sviluppatori che utilizzano .NET familiarità con interfacce insieme come IList <T>, IEnumerable <T> e IDictionary < K, V >. I progetti CLR WinRT insieme le interfacce ai loro equivalenti .NET e nasconde anche il WinRT interfacce che gli sviluppatori non hanno a che fare con due insiemi funzionalmente equivalente di tipi che fanno la stessa cosa.

Oltre a proiettare questi tipi quando appaiono come parametri e restituiscono tipi di metodi, CLR anche deve proiettare queste interfacce quando appaiono nell'elenco interfaccia implementazione di un tipo. Ad esempio, il tipo di WinRT PropertySet implementa il WinRT IMap < string, object > interfaccia. CLR, tuttavia, sarà progetto PropertySet come un tipo che implementa IDictionary < string, object >. Quando si esegue questa proiezione, i membri di PropertySet che vengono utilizzati per implementare IMap < string, object > sono nascosti. Invece, gli sviluppatori .NET accedere PropertySet attraverso corrispondenti IDictionary < string, object > Metodi. Ecco una vista parziale di PropertySet come codificato in 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()
  }
}

Ed ecco una vista parziale di PropertySet dopo la proiezione di 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()
  {
  }
}

Si noti che si verificano le proiezioni di tre tipi: IMap < string, object > IDictionary < string, object >, IKeyValuePair < string, object > KeyValuePair < string, object > e IIterable <IKeyValuePair> a <KeyValuePair> di IEnumerable. Si noti inoltre che il metodo get_Size da IMap è nascosto.

Tipi con .NET Framework aiutanti il Windows Runtime dispone di diversi tipi che non hanno una completa Unione punto nel sistema di tipo .NET, ma sono abbastanza importante per la maggior parte delle applicazioni che il .NET Framework fornisce metodi di supporto per lavorare con loro. Due dei migliori esempi sono le interfacce di flusso e async WinRT.

Anche se il CLR non progetto Windows.Storage.Streams.IRandomAccess­flusso di System.Stream, forniscono un insieme di metodi di estensione per IRandom­AccessStream che consente al codice di trattare questi flussi WinRT come se fossero flussi .NET. Ad esempio, è possibile leggere un flusso di WinRT con StreamReader .NET facilmente chiamando il metodo di estensione OpenStreamForReadAsync.

Il Runtime di Windows fornisce un set di interfacce che rappresentano le operazioni asincrone, ad esempio l'interfaccia IAsyncInfo. Nel .NET Framework 4.5, c'è il supporto incorporato per in attesa di operazioni asincrone, che gli sviluppatori desiderano utilizzare con WinRT APIs allo stesso modo che lo fanno per le API .NET.

Per consentire ciò, il .NET Framework fornito con un set di metodi di estensione GetAwaiter per le interfacce di async WinRT. Questi metodi sono utilizzati da c# e Visual Basic compilatori per consentire operazioni asincrone in attesa di WinRT. Ecco un esempio:

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();
    }
}

Transizione tra il .NET Framework e Windows Runtime The CLR fornisce un meccanismo per il codice gestito perfettamente chiamare WinRT APIs e per il Runtime di Windows chiamata indietro nel codice gestito.

Al livello più basso, il Runtime di Windows è costruito sulla base di concetti COM, quindi non sorprende che il supporto di Common Language Runtime per chiamare WinRT APIs è costruito sulla base esistente infrastruttura di interoperabilità COM.

Una differenza importante, tra interoperabilità WinRT e interoperabilità COM è quanto meno la configurazione che hai a che fare con il runtime di Windows. WinMD file hanno ricchi metadati che descrivono tutte le API che espone con un ben definito mapping per il sistema di tipo .NET, quindi non non c'è alcuna necessità di utilizzare gli attributi MarshalAs nel codice gestito. Allo stesso modo, perché Windows 8 navi con WinMD file per sua WinRT APIs, non è necessario avere un assembly di interoperabilità primario in bundle con l'applicazione. CLR utilizza invece i file WinMD in scatola per capire che tutto che ha bisogno di sapere come chiamare WinRT APIs.

Questi file di WinMD forniscono le definizioni del tipo gestito che vengono utilizzate in fase di esecuzione per consentire agli sviluppatori gestiti accesso al Runtime di Windows. Anche se le API che CLR legge da un file WinMD contengono una definizione di metodo è formattata per essere facilmente utilizzato da codice gestito, l'API WinRT sottostante utilizza una diversa firma API (a volte indicato come application binary interface o ABI, firma). Un esempio di una differenza tra le firme di API e ABI è che, come standard COM, WinRT APIs restituiscono HRESULT e il valore restituito di una API WinRT è in realtà un parametro di output nella firma ABI. Vi mostrerò un esempio di come una firma di metodo gestito si trasforma in una firma di WinRT ABI quando guardo come Common Language Runtime chiama un'API WinRT più avanti in questo articolo.

Runtime Callable Wrapper e COM

Quando un oggetto WinRT entra nel CLR, è necessario essere richiamabile come se fosse un oggetto .NET. Per fare questo accadere, CLR avvolge ogni oggetto WinRT in un runtime callable wrapper (RCW). RCW è codice gestito interagisce con ed è l'interfaccia tra il codice e l'oggetto WinRT che utilizza il codice.

Al contrario, quando gli oggetti gestiti vengono utilizzati dal Runtime di Windows, hanno bisogno di essere chiamato come se fossero oggetti WinRT. In questo caso, gli oggetti gestiti sono avvolti in un COM callable wrapper (CCW) quando mandarono al Runtime di Windows. Poiché il Runtime di Windows utilizza l'infrastruttura stessa come COM, può interagire con CCW per accedere alle funzionalità dell'oggetto gestito (vedere Figura 3).

Using Wrappers for Windows Runtime and Managed Objects
Figura 3 con wrapper per Windows Runtime e oggetti gestiti

Categoria: marshalling

Quando il codice gestito passa attraverso qualsiasi limite di interoperabilità, inclusi i confini WinRT, devono verificarsi diverse cose:

  1. Convertire i parametri di input gestiti in equivalenti di WinRT, tra cui edificio CCW per gli oggetti gestiti.
  2. Trovare l'interfaccia che implementa il metodo WinRT chiamato da che viene chiamato il metodo su RCW.
  3. Chiamare il metodo WinRT.
  4. Convertire i parametri di output di WinRT (compresi i valori di ritorno) in equivalenti gestiti.
  5. Convertire qualsiasi errore HRESULT dall'API WinRT in un'eccezione gestita.

Queste operazioni avvengono in un troncone di marshalling, che Common Language Runtime genera a favore del programma. Gli stub marshalling su un RCW sono codice gestito in realtà chiama prima transizione in un API WinRT. Analogamente, il chiama Windows Runtime stub marshalling CLR generati su un CCW quando passa nel codice gestito.

Categoria: marshalling forniscono il ponte che attraversa il divario tra il Runtime di Windows e il Framework .NET. Capire come funzionano ti aiuterà a ottenere una più profonda comprensione di ciò che accade quando il programma si chiama nel Runtime di Windows.

Un' chiamata di esempio

Immaginate un API WinRT che accetta un elenco di stringhe e concatenati con una stringa di separazione tra ogni elemento. Questa API potrebbe avere una firma gestita come:

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

Il CLR deve chiamare il metodo, come definito in ABI, quindi ha bisogno di capire la firma ABI del metodo.Per fortuna, una serie di trasformazioni deterministiche può essere applicata per ottenere senza ambiguità una firma ABI data una firma API.La prima trasformazione è quello di sostituire i tipi di dati proiettati con i loro equivalenti di WinRT, che restituisce l'API per la forma in cui è definito nel file WinMD prima la scheda metadati caricato.In questo caso, IEnumerable <T> è in realtà una proiezione del IIterable <T>, quindi la vista WinMD di questa funzione è in realtà:

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

WinRT stringhe vengono memorizzate in un tipo di dati HSTRING per il Runtime di Windows, questa funzione in realtà appare come:

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

A livello di ABI, dove la chiamata si verifica effettivamente, WinRT APIs hanno HRESULT restituiscono valori e il valore restituito dalla loro firma è un parametro di output.Inoltre, gli oggetti sono puntatori, quindi sarebbe la firma ABI per questo metodo:

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

Tutti i metodi di WinRT devono essere parte di un'interfaccia che implementa un oggetto. Il nostro metodo Join, per esempio, potrebbe essere parte di un'interfaccia di IConcatenation supportata da una classe StringUtilities. Prima di effettuare un metodo di chiamare in Join, il CLR deve ottenere una sospensione del puntatore all'interfaccia IConcatenation per effettuare la chiamata su.

Il lavoro di uno stub di marshalling è convertire dall'originale gestita chiamata su un RCW a WinRT chiamata finale su un'interfaccia di WinRT. In questo caso, lo pseudo-codice per il marshalling stub potrebbe sembrare Figura 4 (con pulitura chiamate omesse per chiarezza).

Figura 4 esempio di uno Stub di marshalling per effettuare una chiamata da Common Language Runtime per il Runtime di 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);
}

In questo esempio, il primo passo è convertire i parametri gestiti da loro rappresentazione gestita a loro rappresentazione WinRT. In questo caso, il codice crea un CCW per il parametro list e converte il parametro System. String in un HSTRING.

Il passo successivo è quello di trovare l'interfaccia WinRT che fornisce l'implementazione di Join. Questo avviene mediante l'emissione di una chiamata all'oggetto di WinRT è avvolto dal RCW che il codice gestito chiamato Join su. Il motivo più comune, che viene generata un'eccezione InvalidCastException da una chiamata al metodo WinRT è se questa chiamata ha esito negativo. Un motivo per cui che questo può accadere è che l'oggetto WinRT non implementa tutte le interfacce di previsto che il chiamante.

Ora si verifica l'azione reale — lo stub di interoperabilità rende la chiamata effettiva al metodo WinRT Join, fornendo un percorso per poter memorizzare il logico restituire valore HSTRING. Se il metodo WinRT non riesce, indica con un HRESULT di errore, che lo stub di interoperabilità converte in un'eccezione e genera. Questo significa che se il codice gestito vede un'eccezione che viene generata da una chiamata al metodo WinRT, è probabile che il chiamata al metodo WinRT restituito un errore HRESULT e CLR ha generato un'eccezione per indicare quello stato di errore al codice.

Il passo finale è quello di convertire i parametri di output da loro rappresentazione WinRT alla loro forma .NET. In questo esempio, il logico restituisce valore è un parametro di output della chiamata Join e deve essere convertito da un HSTRING in una stringa di .NET. Questo valore può quindi essere restituito come risultato dello stub.

Chiamata da Windows Runtime nel codice gestito

Chiamate che provengono dal Runtime di Windows e destinazione gestito codice opera in modo simile. CLR risponde alle chiamate QueryInterface che il componente Runtime Windows fa contro di esso con un'interfaccia che ha una tabella di funzioni virtual è compilata con i metodi stub di interoperabilità. Queste matrici svolgono la stessa funzione di quello che ho mostrato in precedenza, ma in senso inverso.

Consideriamo il caso dell'API di unire ancora una volta, tranne questa volta assumere esso è implementato nel codice gestito e viene chiamato da un componente Runtime Windows in. Pseudocodice per uno stub che permette questa transizione avvenga potrebbe sembrare Figura 5.

Figura 5 esempio di uno Stub marshalling per effettuare una chiamata dal Runtime Windows a 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;
}

In primo luogo, questo codice converte i parametri di input i tipi di dati di WinRT in tipi gestiti. Supponendo che l'elenco di input è un oggetto WinRT, lo stub deve ottenere un RCW per rappresentare l'oggetto per consentire al codice gestito di usarlo. Il valore della stringa è semplicemente convertito da un HSTRING a System. String.

Successivamente, la chiamata viene effettuata in implementazione gestita del metodo Join sul CCW. Se questo metodo genera un'eccezione, lo stub di interoperabilità intercetta e lo converte in un errore HRESULT restituito al chiamante WinRT. Questo spiega perché alcune eccezioni generate dal codice gestito, chiamato dai componenti di Runtime di Windows non crash il processo. Se il componente Runtime Windows gestisce l'HRESULT di errore, che è effettivamente la stessa cattura e gestisce l'eccezione generata.

Il passo finale è quello di convertire il parametro di output dal relativo tipo di dati .NET per il tipo di dati equivalente WinRT, conversione in questo caso lo System in un HSTRING. Il valore restituito viene quindi posizionato nel parametro di output e un successo che viene restituito HRESULT.

Interfacce proiettate

Prima, ho accennato che CLR proietterà alcune interfacce WinRT in equivalente .NET interfacce. Per esempio, IMap < K, V > è proiettato a IDictionary < K, V >. Questo significa che qualsiasi mappa di WinRT è accessibile come un dizionario .NET e viceversa. Per abilitare questa proiezione al lavoro, un altro set di stub è necessario implementare l'interfaccia WinRT in termini di interfaccia .NET che è progettato a e viceversa. Ad esempio, IDictionary < K, V > dispone di un metodo TryGetValue ma IMap < K, V > non contiene questo metodo. Per consentire gestiti ai chiamanti di utilizzare il metodo TryGetValue, Common Language Runtime fornisce uno stub che implementa questo metodo in termini di metodi che dispongono di IMap. Questo potrebbe essere simile a Figura 6.

Figura 6 concettuale implementazione di IDictionary in termini di 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;
}

Si noti che per fare il suo lavoro, questo stub conversione rende diverse chiamate per l'implementazione sottostante di IMap. Per esempio, diciamo che hai scritto il seguente bit di codice gestito per vedere se un oggetto Windows.Foundation.Collections.PropertySet contiene la chiave "NYJ":

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

Come la chiamata del metodo TryGetValue determina se l'insieme di proprietà contiene la chiave, lo stack di chiamate potrebbe sembrare Figura 7.

Figura 7 Stack di chiamata per chiamata TryGetValue

Stack Descrizione
PropertySet::HasKey Implementazione di WinRT PropertySet
HasKey_Stub Marshalling stub conversione chiamata HasKey dello stub dizionario in una chiamata di WinRT
TryGetValue_Stub Tronchetto di implementazione di IDictionary in termini di IMap
Application Codice applicazione chiamata PropertySet.TryGetValue gestito

Conclusioni

Supporto per Windows Runtime CLR consente agli sviluppatori gestiti chiamata API WinRT definite nel file WinMD come facilmente possono chiamare le API gestite definite in un assembly .NET standard. Sotto il cofano, Common Language Runtime utilizza una scheda metadati per eseguire proiezioni che consentono di unire il sistema di tipo WinRT con il sistema di tipo .NET. Utilizza anche un set di stub di interoperabilità per consentire al codice .NET chiamare i metodi WinRT e viceversa. Prese insieme, queste tecniche rendono facile per gli sviluppatori gestiti per chiamare WinRT APIs dalle loro applicazioni Windows Store.

Shawn Farkas ha lavorato su Common Language Runtime per 10 anni ed è attualmente il responsabile dello sviluppo responsabile della proiezione Windows Runtime CLR e interoperabilità .NET. Prima di Microsoft .NET Framework 4.5, ha lavorato sul modello di sicurezza di Common Language Runtime. Suo blog può essere trovato alla blogs.msdn.com/shawnfa.

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Ryan Byington, Layla Driscoll e Yi Zhang