web-dev-qa-db-fra.com

C # utilise System.Type comme paramètre générique

J'ai une liste de types (System.Type) qui doivent être interrogés sur la base de données.

Pour chacun de ces types, je dois appeler la méthode d'extension suivante (qui fait partie de LinqToNhibernate):

Session.Linq<MyType>()

Cependant, je n'ai pas MyType, mais je veux utiliser un type à la place.

Ce que j'ai c'est:

System.Type typeOne;

Mais je ne peux pas effectuer les opérations suivantes:

Session.Linq<typeOne>()

Comment utiliser un type comme paramètre générique?

75
Jan

Vous ne pouvez pas, directement. Le but des génériques est de fournir une sécurité de type temps de compilation, où vous connaissez le type qui vous intéresse au moment de la compilation et pouvez travailler avec des instances de ce type. Dans votre cas, vous ne connaissez que le Type donc vous ne pouvez pas obtenir de vérifications au moment de la compilation que les objets que vous avez sont des instances de ce type.

Vous devrez appeler la méthode par réflexion - quelque chose comme ceci:

// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq", 
                                BindingFlags.Public | BindingFlags.Static);

// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);

Si vous devez beaucoup utiliser ce type, vous trouverez peut-être plus pratique d'écrire votre propre méthode générique qui appelle toutes les autres méthodes génériques dont elle a besoin, puis d'appeler la méthode your avec réflexion.

81
Jon Skeet

Pour ce faire, vous devez utiliser la réflexion:

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);

(en supposant que Linq<T>() est une méthode statique sur le type Session)

Si Session est en fait un objet, vous aurez besoin de savoir où la méthode Linq est réellement déclarée et de passer Session comme argument :

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});
28
Marc Gravell