C# Iterate through Class properties

C#PropertiesLoops

C# Problem Overview


I'm currently setting all of the values of my class object Record.

This is the code that I'm using to populate the record at the moment, property by property.

// Loop through each field in the result set
for (int i = 0; i <= resultItems.Length; i++)
{

    Record newRecord = new Record()
    {
            itemtype =   resultItems[i - (fieldCount - 0)],
            itemdesc =   resultItems[i - (fieldCount - 1)],
            prodcode =   resultItems[i - (fieldCount - 2)],
            proddesc =   resultItems[i - (fieldCount - 3)],
            curstat =    resultItems[i - (fieldCount -4)],
            totfree =    resultItems[i - (fieldCount -5)],
            totphys =    resultItems[i - (fieldCount -6)],
            pcolgroup =  resultItems[i - (fieldCount -7)],
            scolgroup =  resultItems[i - (fieldCount -8)],
            totpo =      resultItems[i - (fieldCount - 9)],
            totso =      resultItems[i - (fieldCount - 10)],
            quality =    resultItems[i - (fieldCount - 11)],
            statusdesc = resultItems[i - (fieldCount - 12)],
            groupcode =  resultItems[i - (fieldCount - 13)],
            qualitydes = resultItems[i - (fieldCount - 14)],
            pcoldesc =   resultItems[i - (fieldCount - 15)],
            scoldesc =   resultItems[i - (fieldCount - 16)],
            pgroupdesc = resultItems[i - (fieldCount - 17)],
    };
}

Can I iterate through each of the properties dynamically without hard coding all of the property names?

Something like so:

// Create new Record instance
Record newRecord = new Record();

for (int e = 0; e < propertyCount.Length - 1; e++)
{
    newRecord[fieldname] = resultItems[i - (fieldCount - e)];
}

C# Solutions


Solution 1 - C#

You could possibly use Reflection to do this. As far as I understand it, you could enumerate the properties of your class and set the values. You would have to try this out and make sure you understand the order of the properties though. Refer to this MSDN Documentation for more information on this approach.

For a hint, you could possibly do something like:

Record record = new Record();

PropertyInfo[] properties = typeof(Record).GetProperties();
foreach (PropertyInfo property in properties)
{
    property.SetValue(record, value);
}

Where value is the value you're wanting to write in (so from your resultItems array).

Solution 2 - C#

// the index of each item in fieldNames must correspond to 
// the correct index in resultItems
var fieldnames = new []{"itemtype", "etc etc "};

for (int e = 0; e < fieldNames.Length - 1; e++)
{
    newRecord
       .GetType()
       .GetProperty(fieldNames[e])
       .SetValue(newRecord, resultItems[e]);
}

Solution 3 - C#

Yes, you could make an indexer on your Record class that maps from the property name to the correct property. This would keep all the binding from property name to property in one place eg:

public class Record
{
    public string ItemType { get; set; }

    public string this[string propertyName]
    {
        set
        {
            switch (propertyName)
            {
                case "itemType":
                    ItemType = value;
                    break;
                    // etc
            }   
        }
    }
}

Alternatively, as others have mentioned, use reflection.

Solution 4 - C#

I tried what Samuel Slade has suggested. Didn't work for me. The PropertyInfo list was coming as empty. So, I tried the following and it worked for me.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }

Solution 5 - C#

Adding to Samuel Slade's response for anyone who chooses that approach (which is excellent). Take into consideration two things:

  1. GetProperties() only gives you a list of PUBLIC properties in your class. (any PRIVATE ones will not be included).
  2. You should be aware that every property you call SetValue() on should have a setter method to do so, or else an ArgumentException will be thrown (i.e.: "The property's set accessor is not found").

Having said that, special care with properties with no setter method like below:

public string Username { get; set; }
public bool HasCar
    {
        get
        {
            return this.Car != null;
        }
    }

Here the first property will be able to be set to the specified value but the second one not because it does not have a setter method. What I do to solve this is use GetSetMethod() over the properties to discriminate the ones with no setter methods like below:

var properties = this.GetType().GetProperties();
foreach(var prop in properties)
{
    if(prop.GetSetMethod() != null) {
        prop.SetValue(this, null);
    };
}

Hope this comment saves you some time!

Cheers

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
QuestionLukeView Question on Stackoverflow
Solution 1 - C#Samuel SladeView Answer on Stackoverflow
Solution 2 - C#jgauffinView Answer on Stackoverflow
Solution 3 - C#Rich O'KellyView Answer on Stackoverflow
Solution 4 - C#AKAView Answer on Stackoverflow
Solution 5 - C#Franco CanovaView Answer on Stackoverflow