C#迭代Class属性

时间:2011-11-16 12:42:36

标签: c# properties loops

我目前正在设置我的类对象Record的所有值。

这是我用来填充记录的代码,属性为属性。

// 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)],
    };
}

我可以动态地遍历每个属性而无需对所有属性名称进行硬编码吗?

像这样:

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

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

5 个答案:

答案 0 :(得分:178)

您可以使用Reflection来执行此操作。据我所知,您可以枚举类的属性并设置值。您必须尝试这一点,并确保您了解属性的顺序。有关此方法的更多信息,请参阅此MSDN Documentation

有关提示,您可能会执行以下操作:

Record record = new Record();

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

value是您想要写入的值(因此来自您的resultItems数组)。

答案 1 :(得分:14)

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

答案 2 :(得分:1)

是的,您可以在Record类上创建一个索引器,该索引器从属性名称映射到正确的属性。这将在一个地方保留从属性名称到属性的所有绑定,例如:

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

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

或者,正如其他人所提到的,使用反射。

答案 3 :(得分:1)

我尝试了 Samuel Slade 的建议。没为我工作。 PropertyInfo 列表将为空。因此,我尝试了以下方法,并且对我有用。

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

答案 4 :(得分:0)

添加到塞缪尔·斯莱德 对任何选择这种方法的人的回应(非常好)。考虑两件事:

  1. GetProperties() 只为您提供类中的 PUBLIC 属性列表。 (不包括任何私人的)。
  2. 您应该知道,您调用 SetValue() 的每个属性都应该有一个 setter 方法来执行此操作,否则将抛出 ArgumentException(即:“未找到该属性的 set 访问器”)。

话虽如此,请特别注意没有 setter 方法的属性,如下所示:

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

这里第一个属性可以设置为指定的值,但第二个属性不能设置,因为它没有设置方法。我为解决这个问题所做的是在属性上使用 GetSetMethod() 来区分那些没有 setter 方法的属性,如下所示:

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

希望这条评论可以为您节省一些时间!

干杯