179

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)];
}
3
  • 3
    Have you tried Reflection? stackoverflow.com/questions/997747/… Commented Nov 16, 2011 at 12:45
  • 1
    pls take a look at this link stackoverflow.com/questions/721441/… Commented Nov 16, 2011 at 12:47
  • Could you explain where and how you would want to maintain the relationship between a property and the index in the resultItems array? Commented Nov 16, 2011 at 12:56

5 Answers 5

338

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

Sign up to request clarification or add additional context in comments.

8 Comments

What if i want to use property.Getvalue(someOtherClassObjectHavingExacltySameProperties) instead of a value? ( I tried this property?.SetValue(objAppointment, property.GetValue(temp)); but it gives me, {"Object does not match target type."} )
@MalikAsif I'm not sure I fully understand, but it sounds like you are trying to load a property from a different type. If you post a question on SO with an example and link it here, I'll take a look for you.
This is an absolute life saver - thank you! I'm iterating through all class properties to check I have a value (before writing it to XML)
@Cordell, how did you do that? I tried property.GetValue() but it asks for an object as parameter.
@user7792598 You need to pass in the object from which you want to get the property value. If you need further help, post another StackOverflow question
|
23
// 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]);
}

5 Comments

This looks good, but I was hoping to do it dynamically, rather than hard coding the fieldnames in there. Is this possible? Thanks
Also it seems that the GetProperty property is not available for my class instance. :/
nope, there need to be a mapping somewhere between the resultItem indexes and the property names.
@Coulton How do you expect to associate each property to an index dynamically? That's not possible.
you can try nameof(Item.Field) instead of "itemtype" to avoid the hard coding as of C# 6.0
4

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

2 Comments

That'll be because your type has only fields on it, not properties!?
what if we had to get values of properties instead of setting em?
4

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

Comments

3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.