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

168

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 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
Sachin Chavan
la source

Réponses:

297

Utiliser 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ément de référence doivent être ajoutés pour accéder à BindingFlags, car il n'y a pas d'entrée "System.Reflection" dans la liste

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

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

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

Vous n'avez pas besoin de spécifier BindingFlags.GetProperty, vous l'utilisez lors de l'appel type.InvokeMember()pour obtenir la valeur d'une propriété.

Brannon
la source
Btw, ne devrait-il pas y avoir des indicateurs de liaison pour cette méthode GetProperties? Comme BindingFlags.Public | BindingFlags.GetPropertyou quelque chose?
Svish
@Svish, vous avez raison :) Il pourrait utiliser des BindingFlags, mais ils sont facultatifs. Vous voulez probablement Public | Exemple.
Brannon
Astuce: Si vous avez affaire à des champs statiques, passez simplement null ici: property.GetValue (null);
alansiqueira27
42

Notez que si l'objet dont vous parlez a un modèle de propriété personnalisé (tel que DataRowViewetc for DataTable), vous devez utiliser TypeDescriptor; la bonne nouvelle est que cela fonctionne toujours bien pour les cours réguliers (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 TypeConverterque le formatage:

    string fmt = prop.Converter.ConvertToString(prop.GetValue(obj));
Marc Gravell
la source
32

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 d'indicateurs de liaison au lieu de la ligne n ° 3

    Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance
    Dim properties() As PropertyInfo = _type.GetProperties(flags)
Sachin Chavan
la source
Merci, il m'aurait fallu trop de temps pour me convertir en VB :)
Brannon
vous pouvez toujours utiliser un convertisseur automatique, il y en a plein sur le web :)
balexandre
1
Oui mais pas aussi bon que le codage manuel. Un notable est le convertisseur de code telerik
Sachin Chavan
Voici comment Telerik aurait converti: gist.github.com/shmup/3f5abd617a525416fee7
shmup
7

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

La réflexion ralentit +/- 1000 x la vitesse d'un appel de méthode, comme indiqué dans The Performance of Everyday Things

NicoJuicy
la source
2

Voici une autre façon de le faire, en utilisant un lambda LINQ:

C #:

SomeObject.GetType().GetProperties().ToList().ForEach(x => Console.WriteLine($"{x.Name} = {x.GetValue(SomeObject, null)}"));

VB.NET:

SomeObject.GetType.GetProperties.ToList.ForEach(Sub(x) Console.WriteLine($"{x.Name} = {x.GetValue(SomeObject, Nothing)}"))
01F0
la source
1

Voilà comment je fais.

foreach (var fi in typeof(CustomRoles).GetFields())
{
    var propertyName = fi.Name;
}
Chris Go
la source
1
Utilisez GetProperties () au lieu de GetFields () si l'objet / la classe contient des propriétés au lieu de champs.
GarDavis du
0
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 de chaîne dans mon objet de contrôle utilisateur Web dont les noms commencent par "Doc".

Jack
la source