API qui s’appuient sur la réflexion
Dans certains cas, l’utilisation de la réflexion dans le code n’est pas évidente et la chaîne d’outils .NET Native ne conserve donc pas les métadonnées nécessaires au moment de l’exécution. Cette rubrique décrit certaines API courantes ou des modèles de programmation courants qui ne sont pas considérés comme faisant partie de l'API de réflexion, mais dont l'exécution s'appuie sur la réflexion. Si vous les utilisez dans votre code source, vous pouvez ajouter des informations les concernant au fichier de directives runtime (.rd.xml) pour que les appels de ces API ne lèvent pas d’exceptions, telles que MissingMetadataException, au moment de l’exécution.
Méthode Type.MakeGenericType
Vous pouvez instancier dynamiquement un type générique AppClass<T>
en appelant la méthode Type.MakeGenericType à l'aide d'un code tel que celui-ci :
var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);
Pour que ce code s'exécute correctement, plusieurs éléments de métadonnées sont nécessaires. Le premier est constitué des métadonnées Browse
pour le type générique non instancié, AppClass<T>
:
<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />
Il permet à l'appel de méthode Type.GetType(String, Boolean) de réussir et de retourner un objet Type valide.
Toutefois, même quand vous ajoutez des métadonnées pour le type générique non instancié, l’appel de la méthode Type.MakeGenericType lève une exception MissingMetadataException :
Cette opération ne peut pas être effectuée en tant que métadonnées pour le type suivant a été supprimée pour des raisons de performances :
App1.AppClass`1<System.Int32>
.
Vous pouvez ajouter la directive runtime suivante au fichier de directives runtime pour ajouter des métadonnées Activate
pour l'instanciation spécifique sur AppClass<T>
de System.Int32 :
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
Activate="Required Public" />
Chaque instanciation AppClass<T>
différente nécessite une directive distincte si elle est créée avec la Type.MakeGenericType méthode et n’est pas utilisée statiquement.
Méthode MethodInfo.MakeGenericMethod
Dans le cas d'une classe Class1
avec une méthode générique GetMethod<T>(T t)
, GetMethod
peut être appelée par réflexion à l'aide d'un code tel que celui-ci :
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);
Pour s'exécuter correctement, ce code nécessite plusieurs éléments de métadonnées :
Les métadonnées
Browse
pour le type dont vous souhaitez appeler la méthode.Les métadonnées
Browse
pour la méthode que vous souhaitez appeler. S'il s'agit d'une méthode publique, l'ajout de métadonnéesBrowse
publiques pour le type conteneur comprend également la méthode.Métadonnées dynamiques pour la méthode que vous souhaitez appeler, afin que le délégué d’appel de réflexion ne soit pas supprimé par la chaîne d’outils .NET Native. Si des métadonnées dynamiques sont manquantes pour la méthode, l'exception suivante est levée quand la méthode MethodInfo.MakeGenericMethod est appelée :
MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
Les directives runtime suivantes garantissent que toutes les métadonnées nécessaires sont disponibles :
<Type Name="App1.Class1" Browse="Required PublicAndInternal">
<MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>
Une directive MethodInstantiation
est obligatoire pour chaque instanciation différente de la méthode qui est appelée dynamiquement, et l'élément Arguments
est mis à jour pour refléter chaque argument d'instanciation différent.
Méthodes Array.CreateInstance et Type.MakeTypeArray
L'exemple suivant appelle les méthodes Type.MakeArrayType et Array.CreateInstance sur un type, Class1
.
Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);
Si aucune métadonnée de tableau n'est présente, l'erreur suivante se produit :
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.
Les métadonnées Browse
pour le type de tableau sont nécessaires à son instanciation de manière dynamique. La directive runtime suivante permet l'instanciation dynamique de Class1[]
.
<Type Name="App1.Class1[]" Browse="Required Public" />