classe générique, comment définir le type au runtime?

J’ai créé une classe générique, mais je connais le type dans l’exécution, pas dans la conception. J’aimerais donc savoir comment définir le type dans l’exécution.

Par exemple, j’ai:

public class MyGenericClass { .... } 

Ensuite, j’essaie de l’utiliser. J’ai une méthode dans une autre classe, qui consum cette classe générique. Dans le constructeur de cette classe, je reçois en paramètre le type que je souhaite. J’ai donc une propriété type dans laquelle je sauvegarde le type dont j’ai besoin. Donc j’essaye ceci:

 MyGenericClass myClass = new MyGenericClass(); 

Mais ça ne marche pas.

Comment définir le type en runtime dans une classe que j’ai créée?

J’utilise C # 4.0.

Merci. Daimroc.

EDIT: Ce que je veux faire est la suivante. J’ai une classe qui doit faire quelques requêtes à la firebase database. Ces requêtes renvoient toujours les mêmes informations, une classe, mais les informations qui contiennent cette classe proviennent de tables différentes. C’est parce que je dois déterminer quelle requête utiliser. Pour décider quelle requête utiliser, j’utilise le type que je reçois.

C’est pour cette raison que je ne connais pas le type dans la conception, mais qu’il est au moment de l’exécution.

Je pourrais utiliser une interface qui serait implémentée par des classes, et utiliser l’interface instanciée avec la classe correcte, mais cela me fait avoir un commutateur ou un if au moment de l’instanciation, et c’est ce que j’essaie d’éviter Je veux quelque chose de plus générique. De plus, si j’utilise cette solution, pour avoir un si au moment de l’instantané, je peux créer la classe générique, de sorte que je n’aurais qu’une classe et qu’elle serait plus facile à gérer.

Vous pouvez créer votre classe d’une autre manière, en transmettant au constructeur le type que vous souhaitez utiliser et en exploitant le mot-clé dynamic .

Par exemple:

 class MyGeneralClass { dynamic myVariable; Type type; public MyGeneralClass(Type type) { this.type = type; myVariable = Activator.CreateInstance(type); //And then if your type is of a class you can use its methods //eg myVariable.MyMethod(); } //If your function return something of type you can also use dynamic public dynamic Function() { return Activator.CreateInstance(type); } } 

Jetez un coup d’œil à la méthode MakeGenericType . Vous pouvez l’utiliser pour créer une instance de Type (pouvant ensuite être utilisée pour créer une instance de ce type) avec des valeurs d’argument génériques déterminées lors de l’exécution. Sachez toutefois que vous aurez besoin de plus de reflection chaque fois que vous traiterez des caractéristiques génériques de cet object. vous ne pouvez pas créer de variable dans le code dont le type est un type générique avec un argument de type variable.

Si vous y réfléchissez, il n’y a aucune raison d’avoir un générique dont le type est déterminé au moment de l’exécution. Les génériques fournissent une typographie forte, mais cela n’est possible que si vous connaissez le type au moment de la compilation. C’est l’un des principaux avantages des médicaments génériques: la sécurité est garantie, car vous savez quelles actions l’object peut effectuer. Au moment de l’exécution, si vous ne savez pas quel type vous obtenez, cela va à l’encontre de cet objective et vous devrez vous plonger dans le monde de la reflection puissant (mais parfois dangereux). Par exemple,

 List list = new List(); foreach (DateTime item in list) item.Minute + ": " + item.Hour 

Étant donné que je connais le type au moment de COMPILE, je peux le stocker dans un conteneur générique et je respecte les règles de sécurité lors de son utilisation. Je sais que l’article a une propriété Minute and Hour.


Si vous souhaitez effectuer une action en fonction du type d’object, utilisez la méthode GetType (). Ceci est votre fenêtre sur l’identification et le traitement du type à l’exécution.

 Result PerformQuery(object unknownObject) { switch (object.GetType()) { case typeof(ThisType): Do This; break; case typeof(ThatType): Do That; break; } } 

Si vous voulez faire quelque chose avec cet object, vous devez connaître le nom de la méthode au moment de la compilation, ce qui signifie que vous pouvez utiliser des interfaces.

 IFood hamburger = new Hamburger(); hamburger.BeEaten(); 

Si vous n’avez pas ou ne voulez pas utiliser d’interface, vous pouvez utiliser la reflection ou la dynamic. Dans ce cas, j’utiliserais dynamic si je connais la méthode à appeler.

 Result PerformQuery(object unknownObject) { if (object.GetType() == typeof(Pizza)) { dynamic pizza = unknownObject; pizza.BakeInOven() // since I checked and know it is type Pizza it is 'somewhat' safe to do this, unless Pizza class changes the name of BakeInOven method. } } 

Enfin, si vous ne connaissez pas la méthode que vous souhaitez appeler au moment de la compilation, vous pouvez utiliser la reflection.

  ssortingng methodName = CalculateWhatMethodShouldBe(); MethodInfo myMethod = unknownObject.GetType().GetMethods().First(m => m.Name == methodName); MethodInfo.Invoke(unknownObject); 

Je n’ai pas assez d’informations sur votre code, mais vous pourriez peut-être utiliser un simple polymorphism:

 public interface IMyInterface { ... } public class MyGenericClass : IMyInterface { .... } IMyInterface myClass = new MyGenericClass(); 

Vous pouvez également associer cela à un modèle de conception d’usine afin qu’une autre classe soit responsable de l’instanciation de vos types en fonction de certaines connaissances d’exécution.

Bien entendu, cela suppose que votre MyGenericClass ne dispose pas de méthodes telles que:

 public T GetT(){...} 

ou si c’est le cas, il existe une relation supplémentaire entre tous les T’types afin que tous aient la superclasse commune, disons BaseT et vous pouvez changer

 public T GetT(){...} 

à:

 public BaseT GetT(){...}