existe-t-il un moyen de récupérer le type à T
partir IEnumerable<T>
de la réflexion?
par exemple
j'ai une IEnumerable<Child>
info variable ; je veux récupérer le type de l'enfant par réflexion
c#
generics
reflection
Usman Masood
la source
la source
Réponses:
Ainsi,
impressions
System.String
.Voir MSDN pour
Type.GetGenericArguments
.Edit: Je pense que cela répondra aux préoccupations dans les commentaires:
Certains objets implémentent plusieurs génériques
IEnumerable
, il est donc nécessaire d'en renvoyer une énumération.Edit: Bien que, je dois dire, c'est une idée terrible pour une classe à implémenter
IEnumerable<T>
pour plus d'unT
.la source
Je ferais juste une méthode d'extension. Cela a fonctionné avec tout ce que je lui ai lancé.
la source
J'avais 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 (de a
PropertyInfo
).La réponse sélectionnée échoue lorsque le type lui-même n'est
typeof(IEnumerable<T>)
pas une implémentation deIEnumerable<T>
.Pour ce cas, les travaux suivants:
la source
Type.GenericTypeArguments
- uniquement pour la version dotNet FrameWork> = 4.5. Sinon, utilisezType.GetGenericArguments
plutôt.Si vous connaissez le
IEnumerable<T>
(via les génériques), alors celatypeof(T)
devrait fonctionner. Sinon (pourobject
, ou le non génériqueIEnumerable
), vérifiez les interfaces implémentées:la source
Type type
paramètre plutôt qu'unobject obj
paramètre: vous ne pouvez pas simplement remplacerobj.GetType()
partype
parce que si vous passez,typeof(IEnumerable<T>)
vous n'obtenez rien. Pour contourner cela, testez letype
lui - même pour voir s'il s'agit d'un générique deIEnumerable<>
, puis de ses interfaces.Merci beaucoup pour la discussion. Je l'ai utilisé 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 devrais partager ici au cas où quelqu'un en aurait également besoin:
la source
someCollection.GetType().GetInterface(typeof(IEnumerable<>).Name)?.GetGenericArguments()?.FirstOrDefault()
Juste utiliser
typeof(T)
EDIT: Ou utilisez .GetType (). GetGenericParameter () sur un objet instancié si vous n'avez pas T.
la source
Une alternative pour les situations plus simples où ce sera soit une utilisation
IEnumerable<T>
ouT
- notez l'utilisation deGenericTypeArguments
au lieu deGetGenericArguments()
.la source
Il s'agit d'une amélioration par rapport à la solution d'Eli Algranti en ce sens qu'elle fonctionnera également là où le
IEnumerable<>
type se trouve à n'importe quel niveau de l'arborescence d'héritage.Cette solution obtiendra le type d'élément de any
Type
. Si le type n'est pas anIEnumerable<>
, il renverra le type passé. Pour les objets, utilisezGetType
. Pour les types, utiliseztypeof
, puis appelez cette méthode d'extension sur le résultat.la source
Je sais que c'est un peu vieux, mais je pense que cette méthode couvrira tous les problèmes et défis mentionnés dans les commentaires. Merci à Eli Algranti pour avoir inspiré mon travail.
la source
Il s'agit d'une fonction récursive qui ira en profondeur d'abord dans 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<IActionResult>>>>>>>>
qui devrait revenir
IActionResult
la source
typeof(IEnumerable<Foo>)
. renverra le premier argument générique - dans ce cas .GetGenericArguments()
[0]
typeof(Foo)
la source
voici comment je le fais habituellement (via la méthode d'extension):
la source
Voici ma version illisible de l'expression de requête Linq.
Notez que la méthode prend également
IEnumerable
en compte le non générique , elle renvoieobject
dans ce cas, car elle prend uneType
instance plutôt qu'une instance concrète comme argument. Au fait, pour x représente l'inconnu , j'ai trouvé cette vidéo insteresting, bien que ce ne soit pas pertinent.la source