Share via


API qui s'appuient sur la réflexion

Dans certains cas, l’utilisation de la réflexion dans le code n’est pas évidente, de sorte que la chaîne d’outils .NET Native ne conserve 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é 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 différente sur AppClass<T> nécessite une directive distincte si elle est créée avec la Type.MakeGenericType méthode et qu’elle n’est pas utilisée de manière statique.

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ées Browse 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" />

Voir aussi