How to loop through all the properties of a class?
Asked Answered
E

8

176

I have a class.

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

I want to loop through the properties of the above class. eg;

Public Sub DisplayAll(ByVal Someobject As Foo)
    For Each _Property As something In Someobject.Properties
        Console.WriteLine(_Property.Name & "=" & _Property.value)
    Next
End Sub
Earlap answered 10/2, 2009 at 7:44 Comment(0)
P
310

Use Reflection:

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

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

for Excel - what tools/reference item must be added to gain access to BindingFlags, as there is no "System.Reflection" entry in the list

Edit: You can also specify a BindingFlags value to type.GetProperties():

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

That will restrict the returned properties to public instance properties (excluding static properties, protected properties, etc).

You don't need to specify BindingFlags.GetProperty, you use that when calling type.InvokeMember() to get the value of a property.

Planetary answered 10/2, 2009 at 7:47 Comment(4)
Btw, shouldn't there be some binding flags for that GetProperties method? Like BindingFlags.Public | BindingFlags.GetProperty or something?Limerick
@Svish, you're right :) It could use some BindingFlags, but they are optional. You probably want Public | Instance.Planetary
Tip: If you are dealing with static fields, then simply pass null here: property.GetValue(null);Tarahtaran
Well obj.GetValue() no longer exists. What is the current way to iterate thru properties and check values in c# 7 or 8? I'm not finding much that works.Norman
S
45

Note that if the object you are talking about has a custom property model (such as DataRowView etc for DataTable), then you need to use TypeDescriptor; the good news is that this still works fine for regular classes (and can even be much quicker than reflection):

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

This also provides easy access to things like TypeConverter for formatting:

    string fmt = prop.Converter.ConvertToString(prop.GetValue(obj));
Shang answered 10/2, 2009 at 9:0 Comment(0)
E
34

VB version of C# given by 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

Using Binding flags in instead of line no.3

    Dim flags As BindingFlags = BindingFlags.Public Or BindingFlags.Instance
    Dim properties() As PropertyInfo = _type.GetProperties(flags)
Earlap answered 10/2, 2009 at 7:53 Comment(4)
Thanks, it would have taken me too long to convert to VB :)Planetary
you can always use a automatic converter, there are plenty in the web :)Ludhiana
Yes but not all as good as hand coding. One notable one is telerik code converterEarlap
Here's how Telerik would have converted: gist.github.com/shmup/3f5abd617a525416fee7Enabling
S
9

Reflection is pretty "heavy"

Perhaps try this 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 slows down +/- 1000 x the speed of a method call, shown in The Performance of Everyday Things

Sabellian answered 17/11, 2011 at 12:46 Comment(0)
K
4

Here's another way to do it, using a LINQ lambda:

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)}"))
Kimbrough answered 21/2, 2017 at 18:33 Comment(0)
D
3

This is how I do it.

foreach (var fi in typeof(CustomRoles).GetFields())
{
    var propertyName = fi.Name;
}
Dialogism answered 6/10, 2017 at 15:17 Comment(1)
Use GetProperties() instead of GetFields() if the object/class contains properties instead of fields.Satyriasis
G
1
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);
        }
    }

I used the code block above to reset all string properties in my web user control object which names are started with "Doc".

Garrot answered 22/8, 2012 at 8:17 Comment(0)
D
0

I using this example to serialze my datas in my custom file (ini & xml mix)


' **Example of class test :**

    Imports System.Reflection
    Imports System.Text    

    Public Class Player
        Property Name As String
        Property Strong As Double
        Property Life As Integer
        Property Mana As Integer
        Property PlayerItems As List(Of PlayerItem)
    
        Sub New()
            Me.PlayerItems = New List(Of PlayerItem)
        End Sub
    
        Class PlayerItem
            Property Name As String
            Property ItemType As String
            Property ItemValue As Integer
    
            Sub New(name As String, itemtype As String, itemvalue As Integer)
                Me.Name = name
                Me.ItemType = itemtype
                Me.ItemValue = itemvalue
            End Sub
        End Class
    End Class
    
' **Loop function of properties**

    Sub ImportClass(varobject As Object)
        Dim MaVarGeneric As Object = varobject
        Dim MaVarType As Type = MaVarGeneric.GetType
        Dim MaVarProps As PropertyInfo() = MaVarType.GetProperties(BindingFlags.Public Or BindingFlags.Instance)

        Console.Write("Extract " & MaVarProps.Count & " propertie(s) from ")
        If MaVarType.DeclaringType IsNot Nothing Then
            Console.WriteLine(MaVarType.DeclaringType.ToString & "." & MaVarType.Name)
        Else
            Console.WriteLine(MaVarType.Namespace & "." & MaVarType.Name)
        End If

        For Each prop As PropertyInfo In MaVarProps
            If prop.CanRead = True Then

                If prop.GetIndexParameters().Length = 0 Then
                    Dim MaVarValue As Object = prop.GetValue(MaVarGeneric)
                    Dim MaVarValueType As Type = MaVarValue.GetType

                    If MaVarValueType.Name.Contains("List") = True Then
                        Dim MaVarArguments As New StringBuilder
                        For Each GenericParamType As Type In prop.PropertyType.GenericTypeArguments
                            If MaVarArguments.Length = 0 Then
                                MaVarArguments.Append(GenericParamType.Name)
                            Else
                                MaVarArguments.Append(", " & GenericParamType.Name)
                            End If
                        Next
                        Console.WriteLine("Sub-Extract: " & prop.MemberType.ToString & " " & prop.Name & " As List(Of " & MaVarArguments.ToString & ")")
                        Dim idxItem As Integer = 0
                        For Each ListItem As Object In MaVarValue
                            Call ImportClass(MaVarValue(idxItem))
                            idxItem += 1
                        Next
                        Continue For
                    Else
                        Console.WriteLine(prop.MemberType.ToString & " " & prop.Name & " As " & MaVarValueType.Name & " = " & prop.GetValue(varobject))
                    End If

                End If
            End If
        Next
    End Sub

' **To test it :**

        Dim newplayer As New Player With {
            .Name = "Clark Kent",
            .Strong = 5.5,
            .Life = 100,
            .Mana = 50
        }
        ' Grab a chest
        newplayer.PlayerItems.Add(New Player.PlayerItem("Chest", "Gold", 5000))
        ' Grab a potion
        newplayer.PlayerItems.Add(New Player.PlayerItem("Potion", "Life", 50))
        ' Extraction & Console output
        Call ImportClass(newplayer)

The preview in Console : Result of the properties loop of a class

Decalogue answered 15/5, 2022 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.