Dieser Artikel wurde maschinell übersetzt.

Windows-Runtime und CLR

Einblicke in das System mit .NET und Windows-Runtime

Shawn Farkas

 

Die Windows-Runtime (WinRT) enthält eine große Anzahl von neuen APIs für Windows Experience-Entwickler. Die CLR-4.5, welche Schiffe als Teil des Microsoft .NET Framework 4.5 in Windows 8 können Entwickler schreiben verwalteter Code für die Verwendung der APIs auf natürliche Weise, gerade als wären sie einer anderen Klassenbibliothek. Sie können einen Verweis auf die Windows-Metadatendatei (WinMD) hinzufügen, die die APIs Sie anrufen möchten definiert und dann genau wie bei einem standard-verwalteten API aufruft. Visual Studio fügt automatisch einen Verweis auf die integrierten eingestellten WinRT APIs für Windows UI Neubauprojekte, sodass Ihre app einfach beginnen kann mit dieser neuen API.

Unter der Haube stellt die CLR die Infrastruktur für verwalteten Code, WinMD-Dateien und Übergang zwischen verwaltetem Code und Windows Runtime zu verbrauchen. In diesem Artikel werde ich einige dieser Details zeigen. Sie kommen Weg mit besser zu verstehen, was hinter den Kulissen geschieht, wenn Ihr verwaltete Programm eine WinRT-API aufruft.

Konsumieren WinMD Dateien aus verwaltetem Code

WinRT APIs sind in WinMD-Dateien, die codiert werden mit dem Dateiformat in ECMA-335 beschrieben definiert (bit.ly/sLILI). Obwohl WinMD Dateien und .NET Framework-Assemblys eine gemeinsame Codierung teilen, sind sie nicht das gleiche. Einer der wichtigsten Unterschiede in den Metadaten beruht auf der Tatsache, dass das Typsystem WinRT des Typsystems .NET unabhängig ist.

Programme wie Visual Studio und c#-Compiler verwenden die CLR-Metadaten-APIs (z. B. IMetaDataImport), .NET Framework-Assembly-Metadaten zu lesen und können jetzt lesen Metadaten von Dateien sowie die WinMD. Da die Metadaten nicht genau das gleiche wie eine .NET-Assembly ist, fügt der CLR-Metadaten-Leser einen Adapter zwischen dem Metadaten-APIs und die WinMD-Datei gelesen wird. Dies ermöglicht die WinMD Dateien gelesen werden, als wären sie .NET Assemblys (siehe Abbildung 1).

The CLR Inserts a Metadata Adapter Between WinMD Files and the Public Metadata Interface
Abbildung 1 die CLR fügt einen Metadaten-Adapter zwischen WinMD-Dateien und die öffentliche Schnittstelle

Mit ILDasm hilft Ihnen die Änderungen zu verstehen, die der CLR-Metadaten-Adapter für eine WinMD-Datei ausführt. Standardmäßig zeigt ILDasm den Inhalt einer WinMD-Datei in seiner rohen Form, wie es auf der Festplatte ohne den CLR-Metadaten-Adapter codiert ist. Jedoch wenn Sie ILDasm den/Project-Kommandozeilen-Parameter übergeben, es ermöglicht die Metadaten-Adapter, und sehen Sie die Metadaten als CLR und verwalteten Werkzeuge werden lesen.

Durch Ausführen von Kopien von ILDasm nebeneinander — eine mit dem Parameter/Project und eine ohne — entdecken Sie leicht die Änderungen, die der CLR-Metadaten-Adapter an einer WinMD-Datei vornimmt.

Der Windows-Runtime und .NET Typsystemen

Eine der wichtigsten Operationen, die der Metadaten-Adapter ausführt ist die WinRT und .NET-Typ-Systeme zusammenführen. Auf hohem Niveau können fünf verschiedene Kategorien WinRT Typen in einer WinMD-Datei angezeigt und von der CLR berücksichtigt werden müssen. Diese Verweise sind in Abbildung 2 aufgeführt. Jede Kategorie genauer betrachten.

Abbildung 2 WinRT Typen für eine WinMD-Datei

Kategorie Beispiele
WinRT Standardtypen Windows.Foundation.Collections.PropertySet, Windows.Networking.Sockets.DatagramSocket
Primitive Typen Byte, Int32, String, Object
Projizierten Typen Windows.Foundation.Uri, Windows.Foundation.DateTime
Projizierte Schnittstellen Windows.Foundation.Collections.IVector <T>, Windows.Foundation.Iclosable
Typen mit .NET-Helfer Windows.Storage.Streams.IInputStream, Windows.Foundation.IasyncInfo

Standardtypen WinRT während der CLR hat spezielle Unterstützung für viele Arten aufgeführt, die Windows-Runtime, die überwiegende Mehrheit der WinRT Typen werden nicht speziell von der CLR überhaupt behandelt. Stattdessen diese Typen für .NET Entwickler unverändert angezeigt und sie können als große Klassenbibliothek verwendet werden, aktivieren Sie Windows-Speicher zu schreiben Anwendungen.

Primitive Typen dieser Satz von primitiven Typen ist kodiert in einer WinMD-Datei mit der gleichen ELEMENT_TYPE-Enumeration, .NET Assemblys verwenden. Die Common Language Runtime interpretiert automatisch diese primitiven Typen, als wären sie die .NET-äquivalente.

Zum größten Teil, arbeitet WinRT primitive Typen nur als .NET primitive Typen zu behandeln. Zum Beispiel hat eine 32-Bit-Ganzzahl das gleiche Bitmuster in der Windows-Runtime wie in .NET, so dass die CLR ein WinRT DWORD als Int32 .NET ohne Probleme behandeln kann. Aber zwei wichtige Ausnahmen sind Zeichenfolgen und Objekten.

In der Windows-Runtime werden Zeichenfolgen mit dem HSTRING-Datentyp dargestellt, die nicht das gleiche wie ein .NET System.String ist. Ebenso bedeutet ELEMENT_TYPE_OBJECT System.Object, .net,, während es IInspectable ** zu Windows Runtime bedeutet. Die CLR muss für Streicher und Objekte Objekte zur Laufzeit konvertieren zwischen den WinRT und .NET Darstellungen der Typen marshallen. Du wirst sehen, wie dieser Marshalling funktioniert in diesem Artikel.

Projiziert Typen gibt es einige vorhandenen grundlegenden .NET-Typen, die Entsprechungen im WinRT Typsystem verfügen. Beispielsweise definiert die Windows Runtime eine TimeSpan-Struktur und eine Uri-Klasse, die die entsprechende Typen in das .NET Framework haben.

Um zu vermeiden, zwingt .NET Entwickler, hin und her zwischen diesen grundlegenden Datentypen zu konvertieren, projiziert die CLR die WinRT-Version entsprechende .NET. Diese Projektionen sind effektiv zusammenführen, Punkte, dass die CLR zwischen .NET und WinRT Typsysteme einfügt.

Z. B. die Windows-Runtime-Syndication­Client.RetrieveFeedAsync API nimmt ein WinRT Uri als Parameter. Anstatt .NET Entwickler erstellen Sie manuell eine neue Windows.Foundation.Uri-Instanz an diese API übergeben, die CLR-Projekte den Typ als System.Uri, dem .NET Entwickler können verwenden den Typ, den sie mit vertrauter sind.

Ein weiteres Beispiel für eine Projektion ist die Windows.Founda­Tion.HResult-Struktur, die von der CLR in den Typ System.Exception projiziert wird. In .NET Entwickler werden verwendet, um sehen Fehlerinformationen vermittelt als Ausnahme und nicht als ein Fehler-HRESULT, also mit einem WinRT-API wie z. B. IAsycn­Info.ErrorCode express Fehlerinformationen wie eine HResult-Struktur nicht das natürliche Gefühl. Stattdessen projiziert die CLR HResult-Ausnahme, die ein WinRT-API wie z. B. IAsyncInfo.ErrorCode für .NET Entwickler mehr verwendbar ist. Hier ist ein Beispiel für die IAsyncInfo ErrorCode-Eigenschaft in Windows.winmd codiert:

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

Und hier ist die IAsyncInfo ErrorCode-Eigenschaft nach der CLR-Projektion:

 

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

Projiziert Schnittstellen The Windows Runtime stellt auch eine Reihe von grundlegenden Schnittstellen, die .NET Entsprechungen haben. Die CLR führt Typ Projektionen auf diese Schnittstellen auch wieder zusammenführen Typsysteme an diesen grundlegenden Punkten.

Die häufigsten Beispiele der projizierten Schnittstellen sind die WinRT Sammlungsschnittstellen, z. B. IVector <T>, IIterable <T> und IMap < K, V >. Entwickler .NET verwenden sind vertraut mit Auflistungsschnittstellen z. B. IList <T>, IEnumerable <T> und IDictionary < K, V >. Die CLR-Projekte Schnittstellen die WinRT Sammlung Schnittstellen zu ihren Äquivalenten .NET und auch blendet die WinRT, damit Entwickler nicht Umgang mit zwei funktionell gleichwertig Gruppen von Typen, die das gleiche tun.

Zusätzlich zu projizieren diese Typen, wenn sie als Parameter erscheinen und von Methoden Rückgabetypen, muss die CLR auch diese Schnittstellen projizieren, wenn sie in der Schnittstellenliste für die Implementierung eines Typs angezeigt werden. Beispielsweise implementiert den WinRT PropertySet-Typ die WinRT IMap < String, Objekt > Schnittstelle. Jedoch wird die CLR PropertySet als Typ Projekt, das IDictionary < String, Objekt > implementiert. Wenn diese Projektion, die Mitglieder der PropertySet durchführen, die zum Implementieren von IMap < String, Objekt > werden ausgeblendet. Stattdessen greifen .NET Entwickler PropertySet über entsprechende IDictionary < String, Objekt > Methoden. Hier ist eine Teilansicht des PropertySet in Windows.winmd codiert:

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

Und hier ist eine Teilansicht des PropertySet nach der CLR-Projektion:

.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()
  {
  }
}

Beachten Sie, dass drei Typ Projektionen auftreten: IMap < String, Objekt > IDictionary < String, Objekt >, < String, Objekt > IKeyValuePair KeyValuePair < String, Objekt > und IIterable <IKeyValuePair> in IEnumerable <KeyValuePair>. Beachten Sie auch, dass die Get_Size-Methode von IMap verborgen ist.

Typen mit .NET Framework Helfer The Windows Runtime hat mehrere Typen, die keine vollständige Zusammenführung in das Typsystem .NET zeigen aber wichtig genug für die meisten Anwendungen, die das .NET Framework Hilfsmethoden, mit ihnen zu arbeiten bietet. Zwei der besten Beispiele sind die WinRT Stream und Async-Schnittstelle.

Obwohl die CLR nicht Windows.Storage.Streams.IRandomAccess Projekt­Stream, System.Stream, es bietet eine Reihe von Erweiterungsmethoden für IRandom­AccessStream, die kann der Code diese WinRT-Streams zu behandeln, als wären sie .NET Bäche. Beispielsweise können Sie leicht einen WinRT Stream mit .NET StreamReader lesen, durch Aufrufen der OpenStreamForReadAsync-Erweiterung-Methode.

Die Windows-Runtime bietet eine Reihe von Schnittstellen, die asynchrone Operationen, z. B. die IAsyncInfo-Schnittstelle darstellt. In .NET Framework 4.5 gibt es integrierter Unterstützung für warten auf asynchrone Operationen, welche Entwickler wollen mit WinRT APIs in der gleichen Weise verwenden, die sie für .NET-APIs zu tun.

Um dies zu ermöglichen, das .NET Framework mit einem Satz von GetAwaiter Erweiterungsmethoden für die WinRT asynchrone Schnittstellen geliefert. Diese Methoden werden von c# und Visual Basic-Compiler verwendet, wartet auf WinRT asynchrone Operationen aktivieren. Hier ein Beispiel:

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

Übergang zwischen .NET Framework und Windows Runtime The CLR bietet einen Mechanismus für verwalteten Code nahtlos WinRT APIs aufrufen und für die Windows-Runtime zurück in verwalteten Code aufrufen.

Auf seiner niedrigsten Stufe ist die Windows-Runtime auf COM-Konzepte, gebaut, so ist es keine Überraschung, die die CLR-Unterstützung beim Aufruf WinRT-APIs auf vorhandene COM-Interop-Infrastruktur aufbaut.

Ein wichtiger Unterschied zwischen WinRT Interop und COM-Interop ist wie viel Konfiguration, die Sie in der Windows-Runtime zu bewältigen haben. WinMD Dateien haben umfangreiche Metadaten beschreiben alle die APIs, die sie mit einer klar definierten Zuordnung zum .NET Typsystem, ausgesetzt sind, so es keine Notwendigkeit gibt, alle MarshalAs-Attribute in verwaltetem Code verwenden. Ähnlich, da Windows 8 mit WinMD-Dateien für seine WinRT APIs geliefert wird, Sie müssen keine primäre Interop-Assembly, die mit Ihrer Anwendung gebündelt haben. Stattdessen verwendet die CLR die mitgelieferte WinMD Dateien alles herausfinden es wissen, zum WinRT APIs aufrufen muss.

Diese WinMD-Dateien enthalten die verwalteten Typ-Definitionen, die zur Laufzeit verwendet werden, um Entwickler verwalteter Anwendungen Zugriff auf die Windows-Laufzeit zu ermöglichen. Obwohl die APIs, die die CLR aus einer WinMD-Datei liest eine Methodendefinition, die formatiert ist enthalten, um problemlos aus verwaltetem Code verwendet werden, die zugrunde liegenden WinRT-API verwendet eine andere API-Signatur (manchmal auch als die Binärschnittstelle oder ABI, Unterschrift). Ein Beispiel für einen Unterschied zwischen den API- und ABI-Signaturen ist wie standard-COM WinRT APIs zurück HRESULTS, und der Rückgabewert einer WinRT-API ist eigentlich ein Output-Parameter in der ABI-Signatur. Ich zeige ein Beispiel dafür, wie eine verwaltete Methodensignatur in einer WinRT ABI-Signatur umgewandelt ist, wenn ich mir anschaue, wie die CLR in diesem Artikel eine WinRT-API aufruft.

Runtime Callable Wrapper und CCWs

Betritt ein WinRT-Objekt die CLR, muss sie aufrufbar sein, als wäre es ein .NET-Objekt. Um dies möglich zu machen, schließt die CLR jedes WinRT-Objekt in einen Runtime callable Wrapper (RCW). Der RCW ist welche verwalteter Code interagiert mit und ist die Schnittstelle zwischen dem Code und das WinRT-Objekt, das mithilfe von Code.

Umgekehrt, wenn aus der Windows-Runtime verwaltete Objekte verwendet werden, müssen sie aufgerufen werden, als wären sie WinRT Objekte. In diesem Fall sind verwaltete Objekte in einen COM callable Wrapper (CCW) eingeschlossen, wenn sie an der Windows-Runtime gesendet sind. Da die Windows-Runtime die gleiche Infrastruktur wie COM verwendet, kann es mit CCWs zu Access-Funktionen für das verwaltete Objekt interagieren (siehe Abbildung 3).

Using Wrappers for Windows Runtime and Managed Objects
Abbildung 3 mithilfe von Wrappern für Windows Runtime und der verwalteten Objekte

Marshallen von Stubs

Beim Übergang von verwalteten Codes über Interop-Grenze, einschließlich der WinRT Grenzen, müssen mehrere Dinge auftreten:

  1. Wandeln Sie verwaltete Eingabeparameter in WinRT Zahlungsmitteläquivalente, einschließlich Aufbau CCWs für verwaltete Objekte.
  2. Finden Sie die Schnittstelle, die implementiert die WinRT-Methode aufgerufen wird, von der RCW, der die Methode aufgerufen wird.
  3. In der WinRT-Methode aufrufen.
  4. Verwalteten Entsprechungen umzuwandeln Sie WinRT Ausgabeparameter (einschließlich Rückgabewerte).
  5. Wandeln Sie Fehler HRESULTS aus der WinRT-API in eine verwaltete Ausnahme.

Diese Operationen kommen in ein Marshalling Stub, die die CLR in Ihrem Programm Namen generiert. Die Marshalling Stubs auf einen RCW sind welche verwalteter Code ruft tatsächlich vor dem Übergang in eine WinRT-API. Ebenso die Windows Runtime ruft in CLR generierte Marshalling gestorben auf ein CCW, sobald es in verwaltetem Code übergeht.

Marshalling gestorben bieten die Brücke, die Kluft zwischen Windows Runtime und das .NET Framework führt. Verständnis ihrer Funktionsweise hilft Sie gewinnen ein tieferes Verständnis was passiert, wenn Ihr Programm in die Windows-Runtime ruft.

Ein Beispiel-Aufruf

Stellen Sie sich eine WinRT-API, die eine Liste von Zeichenfolgen und verkettet diese, mit ein Trennzeichen zwischen den einzelnen Elementen. Diese API möglicherweise wie eine verwaltete Signatur:

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

Die CLR verfügt die-Methode aufrufen, wie sie im ABI, definiert ist, so muss es die ABI-Signatur der Methode herauszufinden. Zum Glück kann eine Reihe von deterministischen Transformationen angewendet werden, um eine ABI-Signatur, die angesichts einer API-Signatur eindeutig zu erhalten. Die erste Transformation ist die projizierten Daten-Typen mit ihren Entsprechungen WinRT zu ersetzen die API zum Formular es in der in der WinMD-Datei definiert ist gibt bevor der Metadaten-Adapter, die sie geladen. In diesem Fall IEnumerable <T> ist eigentlich eine Projektion des IIterable <T>, so dass der WinMD auf diese Funktion eigentlich ist:

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

WinRT Zeichenfolgen werden in ein HSTRING-Datentyp gespeichert zu Windows Runtime, diese Funktion tatsächlich aussieht:

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

Auf der ABI-Ebene, wo eigentlich der Aufruf erfolgt, WinRT APIs haben HRESULT-Werte zurückgeben, und der Rückgabewert aus ihrer Signatur ist ein Output-Parameter. Zusätzlich werden Objekte Zeigern, also die ABI-Signatur für diese Methode wäre:

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

Alle WinRT Methoden müssen Teil einer Schnittstelle sein, die ein Objekt implementiert. Unsere Join-Methode, könnte zum Beispiel eine IConcatenation-Schnittstelle, unterstützt durch eine StringUtilities-Klasse angehören. Bevor Sie einen Methodenaufruf in Join vornehmen, muss die CLR den IConcatenation-Schnittstellenzeiger für den Anruf auf ergattern.

Die Aufgabe des Marshalling-Stub ist vom Original konvertieren ihn auf einen RCW in die endgültige WinRT Anruf auf einer WinRT-Schnittstelle verwaltet. In diesem Fall der Pseudocode für das Marshalling Stub aussehen könnte Abbildung 4 (mit Bereinigung Anrufe aus Gründen der Übersichtlichkeit weggelassen).

Abbildung 4 Beispiel für eine Marshalling Geburtsdatum für einen Anruf von der CLR für die Windows-Runtime

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 diesem Beispiel ist der erste Schritt, die verwalteten Parameter von ihr verwaltete Darstellung WinRT Darstellung zu konvertieren. In diesem Fall wird der Code erstellt einen CCW für den Listenparameter und konvertiert den System.String-Parameter in einem HSTRING.

Der nächste Schritt ist die WinRT-Schnittstelle zu finden, die die Umsetzung der Verknüpfung liefert. Dies geschieht durch Erteilung eines QueryInterface-Aufrufs auf das WinRT-Objekt, das umschlossen wird von der RCW, die verwaltete Code aufgerufen begleiten Sie auf. Die häufigste Grund, warum, die eine InvalidCastException, von einem Methodenaufruf WinRT ausgelöst wird, ist wenn diese QueryInterface-Aufruf fehlschlägt. Ein Grund, warum dies geschehen kann, ist, dass das WinRT-Objekt nicht alle Schnittstellen implementiert, denen der Aufrufer erwartet.

Jetzt die eigentliche Aktion auftritt — die Interop-Stub macht den eigentlichen Aufruf der WinRT Join-Methode, die Lage für sie zum Speichern von logischen Wert HSTRING zurück. Die WinRT-Methode fehlschlägt, weist es dies mit einem Fehler HRESULT, die Interop-Stub konvertiert in eine Ausnahme und löst. Dies bedeutet, dass wenn der verwaltete Code eine Ausnahme ausgelöst wird, von einem Methodenaufruf WinRT sieht, es wahrscheinlich ist, dass die WinRT-Methode aufgerufen wird ein Fehler zurückgegeben HRESULT und CLR Ausnahmefehler um dieses Staates Fehler Code anzugeben.

Der letzte Schritt ist die Ausgabeparameter aus ihrer WinRT Darstellung ihrer .NET-Format konvertieren. In diesem Beispiel Rückgabewerte der logischen ist ein Output-Parameter des Aufrufs Join und muss von einer HSTRING in eine .NET-Zeichenfolge konvertiert werden. Dieser Wert kann dann als Ergebnis der Stub zurückgegeben werden.

Aus der Windows-Runtime aufrufen in verwalteten Code

Anrufe, die von der Windows-Runtime und Ziel stammen verwalteten Code Arbeit in ähnlicher Weise. Die CLR reagiert auf die QueryInterface Aufrufe der Common Language Runtime-Komponente in Windows dagegen mit einer Schnittstelle mit eine virtuellen Funktion-Tabelle, die mit Interop-Stubmethoden ausgefüllt wird. Diese Kommune erfüllen dieselbe Funktion wie die, die ich vorher, aber in umgekehrter Richtung zeigte.

Betrachten Sie den Fall der Join-API wieder, außer dieser Zeit davon ausgehen, es ist in verwaltetem Code implementiert und in von einer Windows-Runtime-Komponente aufgerufen wird. Pseudocode für ein Stub, der diesen Übergang auftritt ermöglicht aussehen könnte Abbildung 5.

Abbildung 5 Beispiel ein Marshalling Stub für einen Anruf aus der Windows-Runtime der 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;
}

Zunächst wandelt dieser Code die Eingabeparameter aus ihrer WinRT-Datentypen in verwalteten Typen. Vorausgesetzt, dass der Eingabeliste ein WinRT-Objekt ist, muss die Stub einen RCW zur Darstellung dieses Objekts in verwaltetem Code verwenden, die es ermöglichen erhalten. Der Zeichenfolgenwert ist einfach von einem HSTRING in ein System.String konvertiert.

Als nächstes erfolgt der Aufruf in die verwaltete Implementierung der Join-Methode auf der CCW. Wenn diese Methode eine Ausnahme auslöst, die Interop-Stub fängt sie und wandelt es in ein Fehler-HRESULT, die an den WinRT Aufrufer zurückgegeben wird. Dies erklärt, warum einige Ausnahmen, die von verwaltetem Code von Windows Runtime-Komponenten aufgerufen, den Prozess zum Absturz nicht. Wenn die Common Language Runtime-Komponente in Windows Fehler HRESULT behandelt wird, ist, die effektiv abfangen und behandeln der ausgelösten Ausnahme identisch.

Der letzte Schritt ist den Output-Parameter in den gleichwertigen WinRT-Datentyp konvertieren in diesem Fall die System.String in eine HSTRING vom .NET-Datentyp konvertieren. Der Rückgabewert wird platziert in der Output-Parameter und ein Erfolg, den HRESULT zurückgegeben wird.

Projizierte Schnittstellen

Erwähnt, dass die CLR wird einige WinRT-Schnittstellen in gleichwertige .NET Schnittstellen zu projizieren. Z.B. IMap < K, V > IDictionary < K, V > projiziert wird. Dies bedeutet, dass jede Karte WinRT zugänglich als .NET Wörterbuch und umgekehrt. Um diese Projektion arbeiten zu ermöglichen, ist eine weitere Reihe von Kommune erforderlich, die WinRT-Schnittstelle im Hinblick auf die .NET-Schnittstelle implementieren, die es zu und umgekehrt projiziert wird. Z. B. IDictionary < K, V > hat eine TryGetValue-Methode, sondern IMap < K, V > Diese Methode enthält nicht. Um verwalteten Aufrufer TryGetValue verwenden zu ermöglichen, bietet die CLR einen Stub, der diese Methode hinsichtlich der Methoden implementiert, die IMap aufweist. Dies könnte ähnlich aussehen Abbildung 6.

Abbildung 6 konzeptionelle Umsetzung des IDictionary in Bezug auf 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;
}

Beachten Sie, dass um seine Arbeit zu tun, diese Konvertierung Stub einige der zugrunde liegenden IMap-Implementierung aufruft. Zum Beispiel nehmen wir an, dass Sie schrieb das folgende Bit von verwaltetem Code zu sehen, ob ein Windows.Foundation.Collections.PropertySet-Objekt den Schlüssel "NYJ enthält":

 

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

B. der TryGetValue-Aufruf bestimmt, ob der Eigenschaftensatz den Schlüssel enthält, die Aufrufliste aussehen könnte Abbildung 7.

Abbildung 7 Call-Stack für TryGetValue-Aufruf

Stack Description
PropertySet::HasKey WinRT PropertySet Umsetzung
HasKey_Stub Marshalling Stub, die Umwandlung der Wörterbuch-Stub HasKey Aufruf in ein WinRT-Aufruf
TryGetValue_Stub Implementiert IDictionary in Bezug auf IMap-Stub
Anwendung (Application) Verwalteten Anwendungscode aufrufen PropertySet.TryGetValue

Zusammenfassung

Die CLR-Unterstützung für die Windows-Runtime kann Entwickler verwaltete Anwendungen aufrufen WinRT APIs definiert in WinMD-Dateien so einfach wie sie verwalteten APIs in einer Norm .NET-Assembly definierten anrufen können. Unter der Haube verwendet die CLR einen Metadaten-Adapter Projektionen durchführen, mit deren Hilfe das Typsystem WinRT mit dem .NET Typsystem zusammenführen. Es nutzt auch eine Reihe von Interop-Kommune damit .NET Code WinRT-Methoden aufrufen kann und umgekehrt. Zusammengenommen erleichtern diese Techniken für Entwickler verwalteter Anwendungen WinRT APIs aus ihren Windows-Speicher-Anwendungen aufrufen.

Shawn Farkas arbeitet seit 10 Jahren auf die CLR und ist derzeit der Entwicklungsleiter verantwortlich für CLR Windows Runtime Projektion und .NET Interop. Vor das Microsoft .NET Framework 4.5, arbeitete er auf dem CLR-Sicherheitsmodell. Seinen Blog finden Sie unter blogs.msdn.com/shawnfa.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Ryan Byington, Layla Driscoll und Yi Zhang