czy jest jakiś sposób, aby odzyskać typ T
od IEnumerable<T>
poprzez odbicie?
na przykład
mam zmienne IEnumerable<Child>
informacje; chcę odzyskać typ dziecka poprzez refleksję
c#
generics
reflection
Usman Masood
źródło
źródło
Odpowiedzi:
W ten sposób
wydruki
System.String
.Zobacz MSDN dla
Type.GetGenericArguments
.Edycja: wierzę, że to rozwiąże obawy w komentarzach:
Niektóre obiekty implementują więcej niż jeden rodzaj,
IEnumerable
więc konieczne jest zwrócenie ich wyliczenia.Edycja: Chociaż, muszę powiedzieć, to okropny pomysł, aby zaimplementować klasę
IEnumerable<T>
dla więcej niż jednejT
.źródło
Zrobiłbym tylko metodę rozszerzenia. To działało ze wszystkim, co w to rzuciłem.
źródło
Miałem podobny problem. Wybrana odpowiedź działa w rzeczywistych instancjach. W moim przypadku miałem tylko typ (od a
PropertyInfo
).Wybrana odpowiedź nie powiedzie się, jeśli sam typ
typeof(IEnumerable<T>)
nie jest implementacjąIEnumerable<T>
.W tym przypadku działa:
źródło
Type.GenericTypeArguments
- tylko dla dotNet FrameWork w wersji> = 4.5. W przeciwnym razie - użyjType.GetGenericArguments
zamiast tego.Jeśli znasz
IEnumerable<T>
(przez generics), totypeof(T)
powinno działać. W przeciwnym razie (dlaobject
lub nieogólneIEnumerable
) sprawdź zaimplementowane interfejsy:źródło
Type type
parametrem, a nie zobject obj
parametrem: nie możesz po prostu zastąpićobj.GetType()
go,type
ponieważ jeśli przekażesztypeof(IEnumerable<T>)
, nic nie otrzymasz. Aby to obejść, przetestujtype
samą siebie, aby zobaczyć, czy jest to generyczna,IEnumerable<>
a następnie jej interfejsy.Bardzo dziękuję za rozmowę. Użyłem go jako podstawy do poniższego rozwiązania, które działa dobrze we wszystkich interesujących mnie przypadkach (IEnumerable, klasy pochodne itp.). Pomyślałem, że powinienem podzielić się tutaj na wypadek, gdyby ktoś również tego potrzebował:
źródło
someCollection.GetType().GetInterface(typeof(IEnumerable<>).Name)?.GetGenericArguments()?.FirstOrDefault()
Po prostu użyj
typeof(T)
EDYCJA: Lub użyj .GetType (). GetGenericParameter () na utworzonym obiekcie, jeśli nie masz T.
źródło
Alternatywa dla prostszych sytuacji, w których będzie to użycie
IEnumerable<T>
lubT
- uwagaGenericTypeArguments
zamiast zamiastGetGenericArguments()
.źródło
Jest to ulepszenie rozwiązania Eli Algranti, ponieważ będzie działać również tam, gdzie
IEnumerable<>
typ znajduje się na dowolnym poziomie w drzewie dziedziczenia.To rozwiązanie pozwoli uzyskać typ elementu z dowolnego
Type
. Jeśli typ nie jest typuIEnumerable<>
, zwróci przekazany typ. W przypadku obiektów użyjGetType
. W przypadku typów użyjtypeof
, a następnie wywołaj tę metodę rozszerzenia w wyniku.źródło
Wiem, że to trochę stare, ale uważam, że ta metoda obejmie wszystkie problemy i wyzwania wymienione w komentarzach. Podziękowania dla Eli Algranti za inspirację do mojej pracy.
źródło
Jest to funkcja rekurencyjna, która przejdzie najpierw w dół listy typów ogólnych, aż uzyska definicję konkretnego typu bez wewnętrznych typów ogólnych.
Testowałem tę metodę z tym typem:
ICollection<IEnumerable<ICollection<ICollection<IEnumerable<IList<ICollection<IEnumerable<IActionResult>>>>>>>>
który powinien wrócić
IActionResult
źródło
typeof(IEnumerable<Foo>)
. zwróci pierwszy argument ogólny - w tym przypadku .GetGenericArguments()
[0]
typeof(Foo)
źródło
tak to zwykle robię (metodą rozszerzenia):
źródło
Oto moja nieczytelna wersja wyrażenia zapytania Linq ...
Zauważ, że metoda bierze również
IEnumerable
pod uwagę nieogólne, zwracaobject
w tym przypadku, ponieważType
jako argument przyjmuje raczej instancję niż konkretną. Nawiasem mówiąc, ponieważ x reprezentuje nieznane , uznałem ten film za interesujący , chociaż nie ma on znaczenia.źródło