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 öffentlichenBrowse
-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" />