Existe-t-il un moyen de récupérer le type T
de IEnumerable<T>
par la réflexion ?
par exemple
j'ai une variable IEnumerable<Child>
info ; Je veux récupérer le type de l'enfant par réflexion.
Existe-t-il un moyen de récupérer le type T
de IEnumerable<T>
par la réflexion ?
par exemple
j'ai une variable IEnumerable<Child>
info ; Je veux récupérer le type de l'enfant par réflexion.
IEnumerable<T> myEnumerable;
Type type = myEnumerable.GetType().GetGenericArguments()[0];
Ainsi,
IEnumerable<string> strings = new List<string>();
Console.WriteLine(strings.GetType().GetGenericArguments()[0]);
imprime System.String
.
Voir MSDN pour Type.GetGenericArguments
.
Edit : Je pense que cela répondra aux préoccupations exprimées dans les commentaires :
// returns an enumeration of T where o : IEnumerable<T>
public IEnumerable<Type> GetGenericIEnumerables(object o) {
return o.GetType()
.GetInterfaces()
.Where(t => t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(t => t.GetGenericArguments()[0]);
}
Certains objets implémentent plus d'un générique IEnumerable
il est donc nécessaire de renvoyer une énumération de ceux-ci.
Edit : Bien que, je dois dire, c'est une idée terrible pour une classe d'implémenter IEnumerable<T>
pour plus d'un T
.
Ou pire encore, écrivez une méthode avec des retours de rendement et essayez d'appeler GetType sur une variable créée avec cette méthode. Le système vous dira qu'il ne s'agit pas d'un type générique. Donc, fondamentalement, il n'y a pas de moyen universel d'obtenir T étant donné une variable d'instance de type IEnumerable<T>.
Ou essayez avec la classe MyClass : IEnumerable<int> {}. Cette classe n'a pas d'interface générique.
Pourquoi se contenter d'obtenir les arguments génériques, puis de récupérer le type dans son indexeur ? C'est juste demander un désastre, surtout quand le langage supporte typeof(T) comme @amsprich le suggère dans sa réponse, qui peut aussi être utilisé avec un type générique ou connu...
J'ai eu un problème similaire. La réponse sélectionnée fonctionne pour les instances réelles. Dans mon cas, je n'avais qu'un type (issu d'une PropertyInfo
).
La réponse sélectionnée échoue lorsque le type lui-même est typeof(IEnumerable<T>)
pas une mise en œuvre de IEnumerable<T>
.
Dans ce cas, la méthode suivante fonctionne :
public static Type GetAnyElementType(Type type)
{
// Type is Array
// short-circuit if you expect lots of arrays
if (type.IsArray)
return type.GetElementType();
// type is IEnumerable<T>;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IEnumerable<>))
return type.GetGenericArguments()[0];
// type implements/extends IEnumerable<T>;
var enumType = type.GetInterfaces()
.Where(t => t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(t => t.GenericTypeArguments[0]).FirstOrDefault();
return enumType ?? type;
}
Ça a sauvé ma journée. Dans mon cas, j'ai ajouté une instruction if séparée pour gérer les chaînes de caractères puisqu'elle implémente IEnumerable<char>.
Si vous connaissez le IEnumerable<T>
(via les génériques), alors il suffit de typeof(T)
devrait fonctionner. Sinon (pour object
ou le non générique IEnumerable
), vérifiez les interfaces mises en œuvre :
object obj = new string[] { "abc", "def" };
Type type = null;
foreach (Type iType in obj.GetType().GetInterfaces())
{
if (iType.IsGenericType && iType.GetGenericTypeDefinition()
== typeof(IEnumerable<>))
{
type = iType.GetGenericArguments()[0];
break;
}
}
if (type != null) Console.WriteLine(type);
Merci beaucoup pour cette discussion. Je m'en suis servi comme base pour la solution ci-dessous, qui fonctionne bien pour tous les cas qui m'intéressent (IEnumerable, classes dérivées, etc). J'ai pensé que je devais la partager ici au cas où quelqu'un en aurait également besoin :
Type GetItemType(object someCollection)
{
var type = someCollection.GetType();
var ienum = type.GetInterface(typeof(IEnumerable<>).Name);
return ienum != null
? ienum.GetGenericArguments()[0]
: null;
}
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.
1 votes
Dans quel contexte ? Qu'est-ce que cet IEnumerable<T> ? Est-ce une instance d'objet envoyée comme argument ? Ou quoi ?