2012-06-02 1 views
25

Ich versuche festzustellen, ob ein Laufzeittyp eine Art Sammlungsart ist. Was ich unten habe funktioniert, aber es scheint komisch, dass ich die Typen nennen muss, die ich für Sammlungsarten in einem Array halte, wie ich es getan habe.Wie ermittelt man, ob es sich bei einem Typ um eine Art Sammlung handelt?

Im folgenden Code liegt der Grund für die generische Logik darin, dass ich in meiner App erwarte, dass alle Sammlungen generisch sind.

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)); 
} 

Wie würde ich diesen Code umgestalten, um intelligenter oder einfacher zu sein?

+0

Eine Sache im Auge zu behalten ist, dass Sie in der Regel nicht wollen, 'string' als eine Sammlung von' char's zu betrachten, auch wenn es 'IEnumerable ' implementiert. – svick

Antwort

48

Wirklich alle diese Typen erben IEnumerable. Sie können nur für sie überprüfen:

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

oder wenn Sie wirklich für ICollection müssen überprüfen:

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

Blick auf "Syntax" Teil:

+0

Haha. Es war wirklich so einfach. Aus irgendeinem Grund dachte ich, das würde nicht funktionieren und ich habe es nicht versucht. –

+1

Die Vererbungshierarchie im Dokument informiert Sie nicht über implementierte Schnittstellen. Aber wenn man sich die Syntax-Sektion ansieht, wird es. – svick

+0

@svick: Was ist public class Liste : IList , ICollection , \t IEnumerable , IList, ICollection, IEnumerable ? – Ruben

2

können Sie diese Hilfsmethode verwenden, um zu überprüfen, ob ein Typ eine offene generische Schnittstelle implementiert. In Ihrem Fall können Sie 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; 
} 

verwenden, oder Sie können für die nicht generische IEnumerable einfach überprüfen. Alle Auflistungsschnittstellen erben von ihm. Aber ich würde keinen Typ nennen, der IEnumerable eine Sammlung implementiert.

+0

Oder verwenden Sie die Lösung [hier gefunden] (http://stackoverflow.com/a/1075059/122781), die neben allgemeinen Schnittstellen auch für generische Typen verwendet werden kann. – HappyNomad

1

Alle von ihnen erben IEnumerable(), eine Einrichtung, die its there Prüfung sollte genug sein:

+3

So führt String zu einem falsch positiven – War

0

Sie Linq verwenden können, suchen Sie nach einem Interface-Namen wie

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

Wenn diese Werte hat, ist eine Instanz IEnumerable.

+3

Also führt String zu einem falsch positiven – War

2

Ich weiß, dieser Thread ist alt, aber hier ist ein modernes Beispiel ab 20. Juli 2015 nach Microsoft is Stichwort.

if(collection is ICollection) return true; 
+0

Die Frage ist, wie festgestellt werden kann, ob ein * Typ * eine Sammlung ist, keine Objektinstanz. –