57 votes

Appeler une méthode générique avec un type dynamique

Disons que j'ai les classes suivantes

 public class Animal { .... }

public class Duck : Animal { ... }

public class Cow : Animal { ... }

public class Creator
{
   public List<T> CreateAnimals<T>(int numAnimals)
   {
      Type type = typeof(T);
      List<T> returnList = new List<T>();
      //Use reflection to populate list and return
   }
}

Maintenant, dans un code plus tard, je veux lire dans quel animal créer.

 Creator creator = new Creator();
string animalType = //read from a file what animal (duck, cow) to create
Type type = Type.GetType(animalType);
List<animalType> animals = creator.CreateAnimals<type>(5);

Maintenant, le problème est que la dernière ligne n'est pas valide. Y a-t-il une manière élégante de le faire alors?

78voto

Kirk Woll Points 34601

Je ne connais pas l'élégant, mais la façon de le faire est :

 typeof(Creator)
    .GetMethod("CreateAnimals")
    .MakeGenericMethod(type)
    .Invoke(creator, new object[] { 5 });

33voto

Jon Skeet Points 692016

Pas vraiment. Vous devez utiliser la réflexion, essentiellement. Les génériques visent vraiment le typage statique plutôt que les types connus uniquement au moment de l'exécution.

Pour utiliser la réflexion, vous devez utiliser Type.GetMethod pour obtenir la définition de la méthode, puis appeler MethodInfo.MakeGenericMethod(type) , puis l'invoquer comme n'importe quelle autre méthode.

4voto

Samuel Points 5878

Essaye ça:

 public List<T> CreateAnimals<T>(int numAnimals) where T : Animal
{
    Type type = typeof(T);
    List<T> returnList = new List<T>();
    //Use reflection to populate list and return
}

Il doit s'assurer que les types autorisés pour CreateAnimals héritent d'Animal. Alors j'espère qu'il n'y aura pas de problème avec List<animalType> animals = creator.CreateAnimals<type>(5);

2voto

KeithS Points 36130

Les clés pour cela sont MakeGenericType() et MakeGenericMethod(). Une fois que vous êtes devenu dynamique avec les types, vous ne pouvez pas vraiment revenir au typage statique. Ce que vous POUVEZ faire est de créer la liste dynamiquement, en utilisant Activator.CreateInstance(typeof(List<>).MakeGenericType(type)) , puis en appelant dynamiquement la méthode générique à l'aide de méthodes réfléchissantes similaires.

0voto

Paul Michalik Points 3060
List<animalType> animals = 
 creator.CreateAnimals<type>(5);

Dans la ligne ci-dessus de votre exemple, animalType et type sont des variables d'exécution, pas des types, donc c'est bien sûr un non-sens. Une version générique n'a de sens que si vous connaissez les types au moment de la compilation, par exemple :

 List<Animal> animals = 
  creator.CreateAnimals<Cow>(5);

où vous auriez à contraindre les types en conséquence. Si les types ne sont pas connus, il faut se fier entièrement à la réflexion...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X