c'è un modo per recuperare il tipo T
da IEnumerable<T>
attraverso la riflessione?ottenendo il tipo T da IEnumerable <T>
ad es.
ho una variabile IEnumerable<Child>
informazioni; Voglio recuperare il tipo del bambino attraverso la riflessione
c'è un modo per recuperare il tipo T
da IEnumerable<T>
attraverso la riflessione?ottenendo il tipo T da IEnumerable <T>
ad es.
ho una variabile IEnumerable<Child>
informazioni; Voglio recuperare il tipo del bambino attraverso la riflessione
IEnumerable<T> myEnumerable;
Type type = myEnumerable.GetType().GetGenericArguments()[0];
Questa convenzione,
IEnumerable<string> strings = new List<string>();
Console.WriteLine(strings.GetType().GetGenericArguments()[0]);
stampe System.String
.
Vedere MSDN per Type.GetGenericArguments
.
Edit: Credo che questo sarà affrontare i problemi nei commenti:
// 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]);
}
Alcuni oggetti implementano più di una generica IEnumerable
quindi è necessario restituire un'enumerazione di loro.
Edit: Anche se, devo dire, è una pessima idea per una classe per implementare IEnumerable<T>
per più di un T
.
Non funzionerà: provalo con myEnumerable = new string [0]. –
O peggio ancora scrivere un metodo con i rendimenti di rendimento e provare a chiamare GetType su una variabile creata con questo metodo. Ti dirà che non è un evento un tipo generico. Quindi, in pratica non esiste un modo universale per ottenere a T una variabile di istanza di tipo IEnumerable
Oppure provare con la classe MyClass: IEnumerable
typeof(IEnumerable<Foo>)
. GetGenericArguments()
[0]
restituirà il primo argomento generico, in questo caso typeof(Foo)
.
Basta usare typeof(T)
EDIT: Oppure utilizzare .GetType() GetGenericParameter() su un oggetto istanziato, se non si dispone di T.
Se si conosce il IEnumerable<T>
(tramite farmaci generici.), quindi solo typeof(T)
dovrebbe funzionare. In caso contrario (per object
, oppure il non generico IEnumerable
), controllare le interfacce implementate:
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);
Alcuni oggetti implementano più di un IEnumerable generico. – jason
@Jason - e in questi casi, la domanda "trova la T" è già una domanda dubbia; Non posso fare nulla per questo ... –
Un piccolo trucchetto per chiunque cerchi di usarlo con un parametro 'Tipo tipo' piuttosto che con un parametro' oggetto obj': non puoi semplicemente sostituire 'obj.GetType()' con 'type' perché se passi in' typeof (IEnumerable
La ringrazio molto per la discussione. L'ho usato come base per la soluzione seguente, che funziona bene per tutti i casi che mi interessano (IEnumerable, classi derivate, ecc.). Penso che dovrei condividere qui nel caso qualcuno ne abbia bisogno anche:
Type GetItemType(object someCollection)
{
var type = someCollection.GetType();
var ienum = type.GetInterface(typeof(IEnumerable<>).Name);
return ienum != null
? ienum.GetGenericArguments()[0]
: null;
}
Farei solo un metodo di estensione. Questo ha funzionato con tutto ciò che ho lanciato.
public static Type GetItemType<T>(this IEnumerable<T> enumerable)
{
return typeof(T);
}
Non funzionerà se il riferimento temporale della compilazione è solo di tipo oggetto. –
Un'alternativa per le situazioni più semplici dove è o sarà un IEnumerable<T>
o T
- uso nota del GenericTypeArguments
invece di GetGenericArguments()
.
Type inputType = o.GetType();
Type genericType;
if ((inputType.Name.StartsWith("IEnumerable"))
&& ((genericType = inputType.GenericTypeArguments.FirstOrDefault()) != null)) {
return genericType;
} else {
return inputType;
}
Ho avuto un problema simile. La risposta selezionata funziona per istanze reali. Nel mio caso ho avuto solo un tipo (da un PropertyInfo
).
La risposta selezionata non riesce quando il tipo stesso è typeof(IEnumerable<T>)
non un'implementazione di IEnumerable<T>
.
Per questo caso le seguenti opere:
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;
}
considerare up-voto la risposta e domanda selezionata se si trova questo codice utile.
Questo è un miglioramento della soluzione di Eli Algranti in quanto funzionerà anche dove il tipo IEnumerable<>
è a qualsiasi livello nell'albero di eredità.
Questa soluzione otterrà il tipo di elemento da qualsiasi Type
. Se il tipo non è un IEnumerable<>
, restituirà il tipo passato. Per gli oggetti, utilizzare GetType
. Per i tipi, utilizzare typeof
, quindi chiamare questo metodo di estensione sul risultato.
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;
}
}
In quale contesto? Che cos'è questo IEnumerable? È un'istanza dell'oggetto inviata come argomento? O cosa? –