Freigeben über


APIs, die auf Reflektion beruhen

In einigen Fällen ist die Verwendung der Spiegelung im Code nicht offensichtlich, und daher behält die .NET Native-Toolkette keine Metadaten bei, die zur Laufzeit benötigt werden. In diesem Thema werden einige gängige APIs oder Programmiermuster behandelt, die nicht als Teil der Reflektions-API betrachtet werden, aber Reflektion benötigen, um erfolgreich ausgeführt zu werden. Wenn Sie diese im Quellcode verwenden, können Sie Informationen darüber in die Laufzeitanweisungsdatei (*.rd.xml) einfügen, sodass Aufrufe dieser APIs zur Laufzeit keine MissingMetadataException-Ausnahme oder sonstige Ausnahmen auslösen.

Type.MakeGenericType-Methode

Sie können einen generischen Typ AppClass<T> dynamisch instanziieren, indem Sie die Type.MakeGenericType-Methode aufrufen. Dazu verwenden Sie Code wie den folgenden:

var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);

Damit dieser Code zur Laufzeit erfolgreich ist, sind mehrere Elemente von Metadaten erforderlich. Das erste sind Browse-Metadaten für den nicht instanziierten generischen Typ AppClass<T>:

<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />

Auf diese Weise kann der Aufruf der Type.GetType(String, Boolean)-Methode erfolgreich sein und ein gültiges Type-Objekt zurückgeben.

Aber auch wenn Sie Metadaten für den nicht instanziierten generischen Typ hinzufügen, löst der Aufruf der Type.MakeGenericType-Methode eine MissingMetadataException-Ausnahme aus:

Dieser Vorgang kann aus Leistungsgründen nicht als Metadaten für den folgenden Typ entfernt werden:

App1.AppClass`1<System.Int32>.

Sie können der Laufzeitdirektivendatei die folgende Laufzeitdirektive hinzufügen, um Activate-Metadaten für die spezifische Instanziierung über AppClass<T> von System.Int32 hinzuzufügen:

<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
                   Activate="Required Public" />

Jede unterschiedliche Instanziierung AppClass<T> erfordert eine separate Direktive, wenn sie mit der Type.MakeGenericType Methode erstellt und nicht statisch verwendet wird.

MethodInfo.MakeGenericMethod-Methode

In einer Klasse Class1 mit einer generischen Methode GetMethod<T>(T t) kann GetMethod durch Reflektion mithilfe von Code wie dem folgenden aufgerufen werden:

Type ct = typeof(Class1);
MethodInfo mi = ct.GetMethod("GetMethod");
Type[] typeArgs = {typeof(int)};
object[] parameters = { 12 };
var method = mi.MakeGenericMethod(typeArgs);
Class1 c = new Class1();
method.Invoke(c, parameters);

Damit dieser Code erfolgreich ausgeführt wird, sind mehrere Elemente von Metadaten erforderlich:

  • Browse-Metadaten für den Typ, dessen Methode Sie aufrufen möchten.

  • Browse-Metadaten für die Methode, die Sie aufrufen möchten. Ist es eine öffentliche Methode, umfasst das Hinzufügen von öffentlichen Browse-Metadaten für den enthaltenden Typ auch die Methode.

  • Dynamische Metadaten für die Methode, die Sie aufrufen möchten, sodass der Spiegelungsaufrufdelegat nicht von der .NET Native-Toolkette entfernt wird. Wenn dynamische Metadaten für die Methode fehlen, wird beim Aufruf der MethodInfo.MakeGenericMethod-Methode die folgende Ausnahme ausgelöst:

    MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
    

Die folgenden Laufzeitanweisungen stellen sicher, dass alle erforderlichen Metadaten verfügbar sind:

<Type Name="App1.Class1" Browse="Required PublicAndInternal">
   <MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>

Für jede unterschiedliche Instanziierung der Methode, die dynamisch aufgerufen wird, ist eine MethodInstantiation-Direktive erforderlich, und das Arguments-Element wird jedem unterschiedlichen Instanziierungsargument entsprechend aktualisiert.

Methoden Array.CreateInstance und Type.MakeTypeArray

Das folgende Beispiel ruft die Methoden Type.MakeArrayType und Array.CreateInstance für einen Typ Class1 auf.

Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);

Wenn keine Array-Metadaten vorhanden sind, führt dies zu folgender Fehlermeldung:

This operation cannot be carried out as metadata for the following type was removed for performance reasons:

App1.Class1[]

Unfortunately, no further information is available.

Browse-Metadaten für den Arraytyp sind erforderlich, um ihn dynamisch zu instanziieren. Die folgende Laufzeitdirektive ermöglicht die dynamische Instanziierung von Class1[].

<Type Name="App1.Class1[]" Browse="Required Public" />

Weitere Informationen