2012-06-02 15 views
25

Próbuję określić, czy typ środowiska wykonawczego jest pewnego rodzaju typem kolekcji. To, co mam poniżej, działa, ale wydaje się dziwne, że muszę wymienić typy, które uważam za typy kolekcji w tablicy, tak jak ja to zrobiłem.Jak ustalić, czy typ jest typem kolekcji?

W poniższym kodzie powodem ogólnej logiki jest to, że w mojej aplikacji oczekuję, że wszystkie kolekcje będą ogólne.

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

Jak mógłbym poprawić ten kod, aby był bardziej inteligentny lub prostszy?

+0

Jedno pamiętać, jest to, że zwykle nie warto rozważyć 'string' jako zbiór' char's, mimo że implementuje IEnumerable '' . – svick

Odpowiedz

48

Naprawdę wszystkie te typy dziedziczą IEnumerable. Można sprawdzić tylko dla niego:

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

czy naprawdę trzeba sprawdzić kolekcji ICollection:

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

spojrzeć na "składni" części:

+0

Haha. To naprawdę było TAK proste. Z jakiegoś powodu myślałem, że to nie zadziała i nie spróbowałem. –

+1

Hierarchia dziedziczenia w dokumencie nie informuje o zaimplementowanych interfejsach. Ale zajrzysz do sekcji Składnia. – svick

+0

@svick: Co public class Lista : IList, kolekcji ICollection , \t IEnumerable , IList, ICollection, IEnumerable ? – Ruben

2

Można użyć tej metody pomocnika do sprawdzenia, jeśli typ implementuje otwarty interfejs rodzajowe. W twoim przypadku można użyć 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; 
} 

Albo można po prostu sprawdzić, czy nie generycznego IEnumerable. Wszystkie interfejsy kolekcji dziedziczą z niego. Ale nie nazwałbym żadnego typu, który implementuje kolekcję w postaci IEnumerable.

+0

Lub użyj rozwiązania [tutaj znalezione] (http://stackoverflow.com/a/1075059/122781), które działa dla typów ogólnych oprócz ogólnych interfejsów. – HappyNomad

1

Wszystkie z nich dziedziczyć IEnumerable(), co oznacza sprawdzenie its there powinno wystarczyć:

+3

Tak samo ciąg znaków prowadzący do fałszywego pozytywu – War

0

Można użyć LINQ, szukać nazwy interfejsu jak

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

Jeśli to ma wartości jest wystąpienie IEnumerable.

+3

Tak więc ciąg znaków prowadzący do fałszywego pozytywu – War

2

Wiem, że ten wątek jest stary, ale tutaj jest współczesny przykład z 20 lipca 2015 roku według słowa kluczowego Microsoft is.

if(collection is ICollection) return true; 
+0

Pytanie brzmi, jak określić, czy * typ * jest zbiorem, a nie instancją obiektu. –

Powiązane problemy