2010-08-25 7 views
31

Voici un code que j'utilise pour obtenir l'état initial de toutes les propriétés publiques dans une classe pour la vérification IsDirty.Comment savoir si un PropertyInfo est une collection

Quel est le moyen le plus simple de voir si une propriété est IEnumerable?

Cheers,
Berryl

protected virtual Dictionary<string, object> _GetPropertyValues() 
    { 
     return _getPublicPropertiesWithSetters() 
      .ToDictionary(pi => pi.Name, pi => pi.GetValue(this, null)); 
    } 

    private IEnumerable<PropertyInfo> _getPublicPropertiesWithSetters() 
    { 
     return GetType().GetProperties().Where(pi => pi.CanWrite); 
    } 

MISE À JOUR

Ce que je blesse faire est d'ajouter quelques extensions de bibliothèque comme suit

public static bool IsNonStringEnumerable(this PropertyInfo pi) { 
     return pi != null && pi.PropertyType.IsNonStringEnumerable(); 
    } 

    public static bool IsNonStringEnumerable(this object instance) { 
     return instance != null && instance.GetType().IsNonStringEnumerable(); 
    } 

    public static bool IsNonStringEnumerable(this Type type) { 
     if (type == null || type == typeof(string)) 
      return false; 
     return typeof(IEnumerable).IsAssignableFrom(type); 
    } 

Répondre

37
if (typeof(IEnumerable).IsAssignableFrom(pi.PropertyType)) 
+25

Notez qu'une chaîne est un IEnumerable trop –

+2

Il résout le problème http://stackoverflow.com/a/40376537/5996253 –

1

Essayez

private bool IsEnumerable(PropertyInfo pi) 
{ 
    return pi.PropertyType.IsSubclassOf(typeof(IEnumerable)); 
} 
+3

J'ai récemment remarqué que 'x.IsSubClassOf (y)' retourne false si x == y. Dans cette situation, si la propriété est réellement de type 'IEnumerable', la fonction renvoie false. –

+1

C'est intéressant, je n'ai honnêtement jamais utilisé cette logique dans ce contexte précis, alors je suis content que vous l'ayez souligné. Merci. –

12

Je suis d'accord avec Fiodor Soikin mais le fait que est Enumerable ne signifie pas que ce soit seulement une collection puisque la chaîne est également Enumerable et renvoie les caractères un par un ...

Je suggère donc l'utilisation

if (typeof(ICollection<>).IsAssignableFrom(pi.PropertyType)) 
+1

Vous avez raison sur la chaîne bien sûr, mais votre solution échoue (essayez-le avec la liste ()). Voyez ma mise à jour pour le code que j'ai utilisé. À votre santé! – Berryl

+1

Ceci échoue car aucun type construit (comme 'List ') ne peut être assigné à un type générique ('ICollection <>') (en fait, vous ne pouvez pas déclarer une variable de type 'ICollection <>'). Il vaut donc mieux utiliser 'typeof (ICollection)' (comme suggéré par l'éditeur), ce qui va aussi le faire fonctionner pour des collections non génériques. –

+0

Très bien en effet – Joanvo

Questions connexes