jest sposób na odzyskanie typu T
z IEnumerable<T>
przez odbicie?uzyskanie typu T z IEnumerable <T>
np.
Mam zmienną IEnumerable<Child>
info; Chcę odzyskać typ dziecka poprzez refleksję
jest sposób na odzyskanie typu T
z IEnumerable<T>
przez odbicie?uzyskanie typu T z IEnumerable <T>
np.
Mam zmienną IEnumerable<Child>
info; Chcę odzyskać typ dziecka poprzez refleksję
IEnumerable<T> myEnumerable;
Type type = myEnumerable.GetType().GetGenericArguments()[0];
thusly,
IEnumerable<string> strings = new List<string>();
Console.WriteLine(strings.GetType().GetGenericArguments()[0]);
drukuje System.String
.
Zobacz MSDN dla .
Edit: Wierzę, że to będzie dotyczyć problemów w komentarzach:
// 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]);
}
Niektóre obiekty realizować więcej niż jeden ogólny IEnumerable
więc konieczne jest, aby powrócić wyliczenie z nich.
Edit: Chociaż, muszę powiedzieć, że to straszny pomysł na klasę wdrożyć IEnumerable<T>
dla więcej niż jednego T
.
To nie zadziała: spróbuj za pomocą myEnumerable = new string [0]. –
Albo jeszcze gorzej napisz metodę z deklaracjami zwrotu i spróbuj wywołać metodę GetType na zmiennej utworzonej za pomocą tej metody. Pokaże ci, że to nie jest wydarzenie rodzajowe. Więc zasadniczo nie ma uniwersalnego sposobu na otrzymanie T zmiennej instancji typu IEnumerable
Lub spróbuj klasą MyClass: IEnumerable
typeof(IEnumerable<Foo>)
. GetGenericArguments()
[0]
zwróci pierwszy ogólny argument - w tym przypadku typeof(Foo)
.
Jeśli znasz IEnumerable<T>
(przez leki generyczne.), a następnie wystarczy typeof(T)
. W przeciwnym razie (na object
lub non-generic IEnumerable
), sprawdź interfejsy realizowane:
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);
Niektóre obiekty implementują więcej niż jeden ogólny IEnumerable. – jason
@Jason - aw tych przypadkach kwestia "znajdź T" jest już wątpliwym pytaniem; Nie mogę nic na to poradzić ... –
Jedna mała próba dla każdego, kto próbuje użyć tego z parametrem 'Type type' zamiast parametru' object obj': nie można po prostu zastąpić 'obj.GetType()' z 'type', ponieważ jeśli przejdziesz w' typeof (IEnumerable
Dziękuję bardzo za dyskusję. Użyłem go jako podstawy dla poniższego rozwiązania, które sprawdza się we wszystkich przypadkach, które mnie interesują (IEnumerable, pochodne klasy itp.). Pomyślałem, że powinienem się z nami podzielić na wypadek, gdyby ktoś tego potrzebował:
Type GetItemType(object someCollection)
{
var type = someCollection.GetType();
var ienum = type.GetInterface(typeof(IEnumerable<>).Name);
return ienum != null
? ienum.GetGenericArguments()[0]
: null;
}
Właśnie opracowałem metodę przedłużenia. To działało ze wszystkim, co na to rzuciłem.
public static Type GetItemType<T>(this IEnumerable<T> enumerable)
{
return typeof(T);
}
Nie zadziała, jeśli odwołanie do czasu kompilacji jest tylko obiektem typu. –
Alternatywą dla prostszych sytuacjach, kiedy to albo będzie to IEnumerable<T>
lub T
- wykorzystanie nuta GenericTypeArguments
zamiast GetGenericArguments()
.
Type inputType = o.GetType();
Type genericType;
if ((inputType.Name.StartsWith("IEnumerable"))
&& ((genericType = inputType.GenericTypeArguments.FirstOrDefault()) != null)) {
return genericType;
} else {
return inputType;
}
Miałem podobny problem. Wybrana odpowiedź działa dla rzeczywistych instancji. W moim przypadku miałem tylko typ (od PropertyInfo
).
Wybrana odpowiedź kończy się niepowodzeniem, gdy sam typ to typeof(IEnumerable<T>)
, a nie wersja.
w tym przypadku następujące prace:
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;
}
Zastanów się prawa głosu wybraną odpowiedź i pytanie, jeśli okaże się to kod przydatna.
Jest to udoskonalenie rozwiązania Eli Algrantiego, ponieważ działa również tam, gdzie typ IEnumerable<>
jest na dowolnym poziomie w drzewie dziedziczenia.
To rozwiązanie otrzyma typ elementu z dowolnego Type
. Jeśli typ nie jest typu IEnumerable<>
, zwróci on przekazany typ. W przypadku obiektów użyj GetType
. W przypadku typów należy użyć typeof
, a następnie wywołać tę metodę rozszerzenia na wyniku.
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;
}
}
W jakim kontekście? Co to jest IEnumerable? Czy jest to instancja obiektu wysłana jako argument? Albo co? –