123 votes

c# foreach (property in object)... Existe-t-il un moyen simple de faire cela ?

J'ai une classe contenant plusieurs propriétés (toutes sont des chaînes de caractères si cela fait une différence).
J'ai également une liste, qui contient de nombreuses instances différentes de la classe.

En créant quelques tests unitaires pour mes classes, j'ai décidé que je voulais boucler chaque objet de la liste et ensuite boucler chaque propriété de cet objet...

Je pensais que faire ça serait aussi simple que...

foreach (Object obj in theList)
{
     foreach (Property theProperties in obj)
     {
         do some stufff!!;
     }
}

Mais ça n'a pas marché ! :( J'obtiens cette erreur...

"L'instruction foreach ne peut pas opérer sur des variables de type 'Application.Object' car 'Application.Object' ne contient pas de définition publique pour 'GetEnumerator'".

Est-ce que quelqu'un connaît un moyen de faire cela sans des tonnes de ifs et de boucles ou sans entrer dans quelque chose de trop complexe ?

6 votes

À l'avenir, veuillez ne pas dire "Ça ne marche pas" dans une question. Précisez plutôt le problème que vous rencontrez (erreur de compilation, etc.). Merci !

3 votes

Mise à jour ! Merci pour l'info Robert

194voto

sll Points 30638

Essayez ceci :

foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties())
{
   // do stuff here
}

Veuillez également noter que Type.GetProperties() possède une surcharge qui accepte un ensemble de drapeaux de liaison afin que vous puissiez filtrer les propriétés selon un critère différent, tel que le niveau d'accessibilité, voir MSDN pour plus de détails : Méthode Type.GetProperties (BindingFlags) Enfin, n'oubliez pas d'ajouter la référence à l'assemblage "system.Reflection".

Par exemple pour résoudre toutes les propriétés publiques :

foreach (var propertyInfo in obj.GetType()
                                .GetProperties(
                                        BindingFlags.Public 
                                        | BindingFlags.Instance))
{
   // do stuff here
}

Veuillez me faire savoir si cela fonctionne comme prévu.

14 votes

Une fois que vous avez la main sur les propriétés des objets, est-il possible de récupérer la valeur de chaque propriété, par exemple un nom ou un code postal ?

4 votes

Comme ceci : propertyInfo .GetValue(obj, null)

48voto

dasblinkenlight Points 264350

Vous pouvez parcourir en boucle toutes les propriétés non indexées d'un objet comme ceci :

var s = new MyObject();
foreach (var p in s.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) {
    Console.WriteLine(p.GetValue(s, null));
}

Desde GetProperties() renvoie à indexeurs ainsi que des propriétés simples, vous avez besoin d'un filtre supplémentaire avant d'appeler GetValue pour savoir qu'il est possible de passer en toute sécurité null comme deuxième paramètre.

Il se peut que vous deviez modifier davantage le filtre afin d'éliminer les propriétés en écriture seulement et les autres propriétés inaccessibles.

1 votes

+1 pour ne faire quelque chose qu'avec les propriétés qui peuvent réellement être utilisées -- vous pourriez également vouloir filtrer les propriétés en écriture seule.

1 votes

@hvd C'est un excellent point sur les propriétés en écriture seule ! Je les avais presque oubliées. Mon code se plante s'il rencontre une propriété dont le nom est null mais je suis sûr que OP trouvera comment obtenir seulement les propriétés dont il a besoin.

44voto

Grant Thomas Points 28280

Vous y êtes presque, vous devez juste obtenir les propriétés du type, plutôt que de vous attendre à ce que les propriétés soient accessibles sous la forme d'une collection ou d'un sac de propriétés :

var property in obj.GetType().GetProperties()

De là vous pouvez y accéder comme suit :

property.Name
property.GetValue(obj, null)

Con GetValue le deuxième paramètre vous permettra de spécifier des valeurs d'index, ce qui fonctionnera avec les propriétés retournant des collections - puisqu'une chaîne de caractères est une collection de caractères, vous pouvez également spécifier un index pour retourner un caractère si nécessaire.

4 votes

J'ai contrarié quelqu'un ? Je suis ouvert à l'idée de savoir ce qui ne va pas, sinon je risque de ne jamais apprendre.

2 votes

Vous avez probablement reçu le downvote lorsque votre code était incorrect (avant votre édition ninja).

22voto

Eric Lippert Points 300275

Bien sûr, pas de problème :

foreach(object item in sequence)
{
    if (item == null) continue;
    foreach(PropertyInfo property in item.GetType().GetProperties())
    {
        // do something with the property
    }
}

1 votes

Pourquoi avoir ajouté cette ligne ? if (item == null) continue; Personnellement, je pense que si vous obtenez un objet nul à ce moment-là, c'est que quelque chose s'est mal passé beaucoup plus tôt et que c'est là que la validation devrait se faire, ou bien ai-je tort ?

0 votes

@Dementic : Bien sûr, nous pourrions dire que la séquence doit contenir des références non nulles.

4voto

Arion Points 17617

Utilisez Reflection pour ce faire

SomeClass A = SomeClass(...)
PropertyInfo[] properties = A.GetType().GetProperties();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X