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.
public static Type GetInnerGenericType(this Type type)
{
// Attempt to get the inner generic type
Type innerType = type.GetGenericArguments().FirstOrDefault();
// Recursively call this function until no inner type is found
return innerType is null ? type : innerType.GetInnerGenericType();
}
Il s'agit d'une fonction récursive qui parcourt en premier la liste des types génériques jusqu'à ce qu'elle obtienne une définition de type concrète sans types génériques internes.
J'ai testé cette méthode avec ce type : ICollection<IEnumerable<ICollection<ICollection<IEnumerable<IList<ICollection<IEnumerable<T>>>>>>>>
qui devrait retourner T
Une alternative pour les situations plus simples où il s'agit soit d'une IEnumerable<T>
o T
- noter l'utilisation de GenericTypeArguments
au lieu de GetGenericArguments()
.
Type inputType = o.GetType();
Type genericType;
if ((inputType.Name.StartsWith("IEnumerable"))
&& ((genericType = inputType.GenericTypeArguments.FirstOrDefault()) != null)) {
return genericType;
} else {
return inputType;
}
Je sais que c'est un peu vieux, mais je pense que cette méthode couvrira tous les problèmes et défis énoncés dans les commentaires. Crédit à Eli Algranti pour avoir inspiré mon travail.
/// <summary>Finds the type of the element of a type. Returns null if this type does not enumerate.</summary>
/// <param name="type">The type to check.</param>
/// <returns>The element type, if found; otherwise, <see langword="null"/>.</returns>
public static Type FindElementType(this Type type)
{
if (type.IsArray)
return type.GetElementType();
// type is IEnumerable<T>;
if (ImplIEnumT(type))
return type.GetGenericArguments().First();
// type implements/extends IEnumerable<T>;
var enumType = type.GetInterfaces().Where(ImplIEnumT).Select(t => t.GetGenericArguments().First()).FirstOrDefault();
if (enumType != null)
return enumType;
// type is IEnumerable
if (IsIEnum(type) || type.GetInterfaces().Any(IsIEnum))
return typeof(object);
return null;
bool IsIEnum(Type t) => t == typeof(System.Collections.IEnumerable);
bool ImplIEnumT(Type t) => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>);
}
Il s'agit d'une amélioration par rapport à la solution d'Eli Algranti, dans la mesure où elle fonctionnera également lorsque l'adresse de l'utilisateur est la suivante IEnumerable<>
se trouve à n'importe quel niveau de l'arbre d'héritage.
Cette solution permettra d'obtenir le type d'élément à partir de n'importe quel Type
. Si le type n'est pas un IEnumerable<>
il retournera le type passé. Pour les objets, utilisez GetType
. Pour les types, utilisez typeof
puis appeler cette méthode d'extension sur le résultat.
public static Type GetGenericElementType(this Type type)
{
// Short-circuit for Array types
if (typeof(Array).IsAssignableFrom(type))
{
return type.GetElementType();
}
while (true)
{
// Type is IEnumerable<T>
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
return type.GetGenericArguments().First();
}
// Type implements/extends IEnumerable<T>
Type elementType = (from subType in type.GetInterfaces()
let retType = subType.GetGenericElementType()
where retType != subType
select retType).FirstOrDefault();
if (elementType != null)
{
return elementType;
}
if (type.BaseType == null)
{
return type;
}
type = type.BaseType;
}
}
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 ?