How can you loop over the properties of a class?

C#Reflection

C# Problem Overview


Is there a way in c# to loop over the properties of a class?

Basically I have a class that contains a large number of property's (it basically holds the results of a large database query). I need to output these results as a CSV file so need to append each value to a string.

The obvious way it to manually append each value to a string, but is there a way to effectively loop over the results object and add the value for each property in turn?

C# Solutions


Solution 1 - C#

Sure; you can do that in many ways; starting with reflection (note, this is slowish - OK for moderate amounts of data though):

var props = objectType.GetProperties();
foreach(object obj in data) {
    foreach(var prop in props) {
        object value = prop.GetValue(obj, null); // against prop.Name
    }
}

However; for larger volumes of data it would be worth making this more efficient; for example here I use the Expression API to pre-compile a delegate that looks writes each property - the advantage here is that no reflection is done on a per-row basis (this should be significantly faster for large volumes of data):

static void Main()
{        
    var data = new[] {
       new { Foo = 123, Bar = "abc" },
       new { Foo = 456, Bar = "def" },
       new { Foo = 789, Bar = "ghi" },
    };
    string s = Write(data);        
}
static Expression StringBuilderAppend(Expression instance, Expression arg)
{
    var method = typeof(StringBuilder).GetMethod("Append", new Type[] { arg.Type });
    return Expression.Call(instance, method, arg);
}
static string Write<T>(IEnumerable<T> data)
{
    var props = typeof(T).GetProperties();
    var sb = Expression.Parameter(typeof(StringBuilder));
    var obj = Expression.Parameter(typeof(T));
    Expression body = sb;
    foreach(var prop in props) {            
        body = StringBuilderAppend(body, Expression.Property(obj, prop));
        body = StringBuilderAppend(body, Expression.Constant("="));
        body = StringBuilderAppend(body, Expression.Constant(prop.Name));
        body = StringBuilderAppend(body, Expression.Constant("; "));
    }
    body = Expression.Call(body, "AppendLine", Type.EmptyTypes);
    var lambda = Expression.Lambda<Func<StringBuilder, T, StringBuilder>>(body, sb, obj);
    var func = lambda.Compile();

    var result = new StringBuilder();
    foreach (T row in data)
    {
        func(result, row);
    }
    return result.ToString();
}

Solution 2 - C#

foreach (PropertyInfo prop in typeof(MyType).GetProperties())
{
    Console.WriteLine(prop.Name);
}

Solution 3 - C#

I tried various recommendations on this page, I couldn't quite get any of them to work. I started with the top answer (you'll notice my variables are similarly named), and just worked through it on my own. This is what I got to work - hopefully it can help someone else.

var prop = emp.GetType().GetProperties();     //emp is my class
    foreach (var props in prop)
      {
        var variable = props.GetMethod;
                                                                 
        empHolder.Add(variable.Invoke(emp, null).ToString());  //empHolder = ArrayList
      }

***I should mention this will only work if you're using get;set; (public) properties.

Solution 4 - C#

You can make a list of oject's properties

  IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();

And then use a foreach to navigate into the list..

   foreach (var property in properties)
            {
              here's code...
            }

Solution 5 - C#

Use something like

StringBuilder csv = String.Empty;
PropertyInfo[] ps this.GetType().GetProperties();
foreach (PropertyInfo p in ps)
{
    csv.Append(p.GetValue(this, null);
    csv.Append(",");
}

Solution 6 - C#

var csv = string.Join(",",myObj
    .GetType()
    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
    .Select(p => p.GetValue(myObj, null).ToString())
    .ToArray());

Solution 7 - C#

this is how to loop over the properties in vb.net , its the same concept in c#, just translate the syntax:

 Dim properties() As PropertyInfo = Me.GetType.GetProperties(BindingFlags.Public Or BindingFlags.Instance)
            If properties IsNot Nothing AndAlso properties.Length > 0 Then
                properties = properties.Except(baseProperties)
                For Each p As PropertyInfo In properties
                    If p.Name <> "" Then
                        p.SetValue(Me, Date.Now, Nothing)  'user p.GetValue in your case
                    End If
                Next
            End If

Solution 8 - C#

Looping over properties

Type t = typeof(MyClass);
foreach (var property in t.GetProperties())
{                
}

Solution 9 - C#

string target = "RECEIPT_FOOTER_MESSAGE_LINE" + index + "Column";
PropertyInfo prop = xEdipV2Dataset.ReceiptDataInfo.GetType().GetProperty(target);
Type t = xEdipV2Dataset.ReceiptDataInfo.RECEIPT_FOOTER_MESSAGE_LINE10Column.GetType();
prop.SetValue(t, fline, null);

Attent for that: target object must be setable

Solution 10 - C#

string notes = "";

Type typModelCls = trans.GetType(); //trans is the object name
foreach (PropertyInfo prop in typModelCls.GetProperties())
{
    notes = notes + prop.Name + " : " + prop.GetValue(trans, null) + ",";
}
notes = notes.Substring(0, notes.Length - 1);

We can then write the notes string as a column to the log table or to a file. You have to use System.Reflection to use PropertyInfo

Solution 11 - C#

getting values of properties from simple class object....

class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var person1 = new Person
        {
            Name = "John",
            Surname = "Doe",
            Age = 47
        };

        var props = typeof(Person).GetProperties();
        int counter = 0;

        while (counter != props.Count())
        {
            Console.WriteLine(props.ElementAt(counter).GetValue(person1, null));
            counter++;
        }
    }
}

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
QuestionSergioView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#StevenView Answer on Stackoverflow
Solution 3 - C#AaronView Answer on Stackoverflow
Solution 4 - C#bANView Answer on Stackoverflow
Solution 5 - C#IveView Answer on Stackoverflow
Solution 6 - C#Dean ChalkView Answer on Stackoverflow
Solution 7 - C#Ali TarhiniView Answer on Stackoverflow
Solution 8 - C#Claus Asbjørn SørensenView Answer on Stackoverflow
Solution 9 - C#Hamit YILDIRIMView Answer on Stackoverflow
Solution 10 - C#Nagaraj RaveendranView Answer on Stackoverflow
Solution 11 - C#donibaloniView Answer on Stackoverflow