How to loop through all the properties of a class?

.Netvb.netClassReflectionProperties

.Net Problem Overview


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

.Net Solutions


Solution 1 - .Net

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.

Solution 2 - .Net

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));

Solution 3 - .Net

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)

Solution 4 - .Net

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

Solution 5 - .Net

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)}"))

Solution 6 - .Net

This is how I do it.

foreach (var fi in typeof(CustomRoles).GetFields())
{
	var propertyName = fi.Name;
}

Solution 7 - .Net

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".

Solution 8 - .Net

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSachin ChavanView Question on Stackoverflow
Solution 1 - .NetBrannonView Answer on Stackoverflow
Solution 2 - .NetMarc GravellView Answer on Stackoverflow
Solution 3 - .NetSachin ChavanView Answer on Stackoverflow
Solution 4 - .NetNicoJuicyView Answer on Stackoverflow
Solution 5 - .Net01F0View Answer on Stackoverflow
Solution 6 - .NetChris GoView Answer on Stackoverflow
Solution 7 - .NetJackView Answer on Stackoverflow
Solution 8 - .NetDukeNugGetView Answer on Stackoverflow