C # Итерация по свойствам класса

118

В настоящее время я устанавливаю все значения своего объекта класса 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)];
}
Люк
источник
1
Вы пробовали Reflection? stackoverflow.com/questions/997747/…
коль
1
Пожалуйста, взгляните на эту ссылку stackoverflow.com/questions/721441/…
Enigma State
Не могли бы вы объяснить, где и как вы хотели бы поддерживать связь между свойством и индексом в массиве resultItems?
Erno

Ответы:

226

Вы могли бы использовать для этого Reflection. Насколько я понимаю, вы можете перечислить свойства своего класса и установить значения. Вам нужно будет попробовать это и убедиться, что вы понимаете порядок свойств. Обратитесь к этой документации MSDN для получения дополнительной информации об этом подходе.

В качестве подсказки вы могли бы сделать что-то вроде:

Record record = new Record();

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

Где valueзначение, которое вы хотите записать (например, из вашего resultItemsмассива).

Сэмюэл Слэйд
источник
1
Что, если я хочу использовать property.Getvalue (someOtherClassObjectHavingExacltySameProperties) вместо значения ? (Я пробовал это свойство? .SetValue (objAppointment, property.GetValue (temp)); но оно дает мне: {"Объект не соответствует целевому типу."} )
Асиф Мехмуд
@MalikAsif Я не уверен, что полностью понимаю, но похоже, что вы пытаетесь загрузить свойство из другого типа. Если вы разместите вопрос о SO с примером и свяжете его здесь, я поищу вас.
Samuel Slade
1
Это абсолютная спасатель - спасибо! Я перебираю все свойства класса, чтобы проверить, есть ли у меня значение (перед записью его в XML)
Корделл
@ Корделл, как ты это сделал? Я пробовал property.GetValue (), но он запрашивает объект в качестве параметра.
user7792598
@ user7792598 Вам необходимо передать объект, из которого вы хотите получить значение свойства. Если вам нужна дополнительная помощь, опубликуйте еще один вопрос на StackOverflow
Сэмюэл Слэйд
17
// 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]);
}
jgauffin
источник
1
Выглядит хорошо, но я надеялся сделать это динамически, а не жестко кодировать имена полей. Это возможно? Спасибо
Люк
Также кажется, что GetPropertyсвойство недоступно для моего экземпляра класса. : /
Люк
нет, должно быть соответствие между индексами resultItem и именами свойств.
jgauffin
1
@Coulton Как вы ожидаете динамически связывать каждое свойство с индексом? Это невозможно.
Эми
вы можете попробовать nameof(Item.Field)вместо того, "itemtype"чтобы избежать жесткого кодирования,
Патрик
2

Да, вы можете создать индексатор для своего класса Record, который сопоставляет имя свойства с правильным свойством. Это сохранит всю привязку имени свойства к свойству в одном месте, например:

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

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

В качестве альтернативы, как уже упоминалось, используйте отражение.

Рич О'Келли
источник
1

Я попробовал то, что предложил Сэмюэл Слейд . У меня не сработало. PropertyInfo Список придет как пустые. Итак, я попробовал следующее, и у меня это сработало.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }
BheemaSenan
источник
1
Это потому, что в вашем типе есть только поля, а не свойства !?
jamheadart