2012-06-02 18 views
25

Sto cercando di determinare se un tipo di runtime è una sorta di tipo di raccolta. Quello che ho qui sotto funziona, ma mi sembra strano che devo nominare i tipi che credo siano tipi di raccolta in un array come quello che ho fatto.Come determinare se un tipo è un tipo di collezione?

Nel codice seguente, il motivo della logica generica è perché, nella mia app, mi aspetto che tutte le raccolte siano generiche.

bool IsCollectionType(Type type) 
{ 
    if (!type.GetGenericArguments().Any()) 
     return false; 

    Type genericTypeDefinition = type.GetGenericTypeDefinition(); 
    var collectionTypes = new[] { typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>), typeof(List<>) }; 
    return collectionTypes.Any(x => x.IsAssignableFrom(genericTypeDefinition)); 
} 

Come dovrei rifattorizziamo questo codice per essere più intelligenti o più semplice?

+0

Una cosa da tenere a mente è che di solito non si vuole prendere in considerazione 'STRING' come una collezione di' char's, anche se implementa IEnumerable '' . – svick

risposta

48

In realtà tutti questi tipi ereditano IEnumerable. È possibile controllare solo per esso:

bool IsEnumerableType(Type type) 
{ 
    return (type.GetInterface(nameof(IEnumerable)) != null); 
} 

o se si ha realmente bisogno di controllare per ICollection:

bool IsCollectionType(Type type) 
{ 
    return (type.GetInterface(nameof(ICollection)) != null); 
} 

Look at parte "sintassi":

+0

Haha. E 'stato davvero così semplice. Per qualche ragione pensavo che non avrebbe funzionato e non l'ho provato. –

+1

La gerarchia di ereditarietà nel documento non indica interfacce implementate. Ma vedremo la sezione Sintassi. – svick

+0

@svick: Che dire Lista public class : IList , ICollection , \t IEnumerable , IList, ICollection, IEnumerable ? – Ruben

2

È possibile utilizzare questo metodo di supporto per controllare se un tipo implementa un'interfaccia generica aperta. Nel tuo caso è possibile utilizzare DoesTypeSupportInterface(type, typeof(Collection<>))

public static bool DoesTypeSupportInterface(Type type,Type inter) 
{ 
    if(inter.IsAssignableFrom(type)) 
     return true; 
    if(type.GetInterfaces().Any(i=>i. IsGenericType && i.GetGenericTypeDefinition()==inter)) 
     return true; 
    return false; 
} 

Oppure si può semplicemente controllare il generico IEnumerable non. Tutte le interfacce di raccolta ne ereditano. Ma non chiamerei nessun tipo che implementa la collezione IEnumerable.

+0

Oppure utilizzare la soluzione [trovata qui] (http://stackoverflow.com/a/1075059/122781) che funziona per tipi generici oltre alle interfacce generiche. – HappyNomad

1

Tutti loro ereditare IEnumerable(), il che significa che il controllo its there dovrebbe essere sufficiente:

+3

Così fa la stringa che porta a un falso positivo – War

0

È possibile utilizzare LINQ, la ricerca di un nome di interfaccia come

yourobject.GetType().GetInterfaces().Where(s => s.Name == "IEnumerable") 

Se questo ha valori è un'istanza di IEnumerable.

+3

Così fa la stringa che porta a un falso positivo – War

2

So che questa discussione è obsoleta, ma qui c'è un esempio moderno a partire dal 20 luglio 2015 secondo la parola chiave Microsoft is.

if(collection is ICollection) return true; 
+0

La domanda è come determinare se un * tipo * è una raccolta, non un'istanza di oggetto. –

Problemi correlati