176 votes

Comment parcourir en boucle toutes les propriétés d'une classe ?

J'ai un cours.

Public Class Foo
    Private _Name As String
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property

    Private _Age As String
    Public Property Age() As String
        Get
            Return _Age
        End Get
        Set(ByVal value As String)
            _Age = value
        End Set
    End Property

    Private _ContactNumber As String
    Public Property ContactNumber() As String
        Get
            Return _ContactNumber
        End Get
        Set(ByVal value As String)
            _ContactNumber = value
        End Set
    End Property

End Class

Je veux parcourir en boucle les propriétés de la classe ci-dessus. Par exemple ;

Public Sub DisplayAll(ByVal Someobject As Foo)
    For Each _Property As something In Someobject.Properties
        Console.WriteLine(_Property.Name & "=" & _Property.value)
    Next
End Sub

309voto

Brannon Points 12633

Utilisez la réflexion :

Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties();

foreach (PropertyInfo property in properties)
{
    Console.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null));
}

pour Excel - quels outils/éléments de référence doivent être ajoutés pour avoir accès aux BindingFlags, car il n'y a pas d'entrée "System.Reflection" dans la liste

Edit : Vous pouvez également spécifier une valeur de BindingFlags pour type.GetProperties() :

BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = type.GetProperties(flags);

Cela limitera les propriétés renvoyées aux propriétés d'instance publiques (à l'exclusion des propriétés statiques, des propriétés protégées, etc.)

Vous n'avez pas besoin de préciser BindingFlags.GetProperty vous l'utilisez lorsque vous appelez type.InvokeMember() pour obtenir la valeur d'une propriété.

0 votes

Par ailleurs, ne devrait-il pas y avoir des indicateurs de liaison pour la méthode GetProperties ? Comme BindingFlags.Public | BindingFlags.GetProperty ou autre ?

0 votes

@Svish, vous avez raison :) Il pourrait utiliser quelques BindingFlags, mais ils sont facultatifs. Vous voulez probablement Public | Instance.

0 votes

Conseil : si vous avez affaire à des champs statiques, passez simplement null ici : property.GetValue(null) ;

45voto

Marc Gravell Points 482669

Notez que si l'objet dont vous parlez possède un modèle de propriété personnalisé (tel que DataRowView etc. pour DataTable ), vous devez alors utiliser TypeDescriptor La bonne nouvelle est que cela fonctionne toujours très bien pour les classes normales (et peut même être beaucoup plus rapide que la réflexion ) :

foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) {
    Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj));
}

Cela permet également d'accéder facilement à des éléments tels que TypeConverter pour le formatage :

    string fmt = prop.Converter.ConvertToString(prop.GetValue(obj));

34voto

Sachin Chavan Points 2252

Version VB de C# donnée par Brannon :

Public Sub DisplayAll(ByVal Someobject As Foo)
    Dim _type As Type = Someobject.GetType()
    Dim properties() As PropertyInfo = _type.GetProperties()  'line 3
    For Each _property As PropertyInfo In properties
        Console.WriteLine("Name: " + _property.Name + ", Value: " + _property.GetValue(Someobject, Nothing))
    Next
End Sub

Utilisation des drapeaux de liaison à la place de la ligne n°3

    Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance
    Dim properties() As PropertyInfo = _type.GetProperties(flags)

0 votes

Merci, cela m'aurait pris trop de temps de convertir en VB :)

0 votes

Vous pouvez toujours utiliser un convertisseur automatique, il y en a plein sur le web :)

1 votes

Oui, mais pas tous aussi bons que le codage manuel. L'un d'entre eux est Telerik Code Converter.

9voto

NicoJuicy Points 892

La réflexion est assez "lourde".

Essayez peut-être cette solution :

C#

if (item is IEnumerable) {
    foreach (object o in item as IEnumerable) {
            //do function
    }
} else {
    foreach (System.Reflection.PropertyInfo p in obj.GetType().GetProperties())      {
        if (p.CanRead) {
            Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj,  null)); //possible function
        }
    }
}

VB.Net

  If TypeOf item Is IEnumerable Then

    For Each o As Object In TryCast(item, IEnumerable)
               'Do Function
     Next
  Else
    For Each p As System.Reflection.PropertyInfo In obj.GetType().GetProperties()
         If p.CanRead Then
               Console.WriteLine("{0}: {1}", p.Name, p.GetValue(obj, Nothing))  'possible function
          End If
      Next
  End If

Reflection ralentit de +/- 1000 x la vitesse d'un appel de méthode, comme le montre l'exemple suivant La performance des objets du quotidien

1voto

Emir Kuzeyli Points 71
private void ResetAllProperties()
    {
        Type type = this.GetType();
        PropertyInfo[] properties = (from c in type.GetProperties()
                                     where c.Name.StartsWith("Doc")
                                     select c).ToArray();
        foreach (PropertyInfo item in properties)
        {
            if (item.PropertyType.FullName == "System.String")
                item.SetValue(this, "", null);
        }
    }

J'ai utilisé le bloc de code ci-dessus pour réinitialiser toutes les propriétés des chaînes de mon objet de contrôle de l'utilisateur Web dont les noms commencent par "Doc".

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