C # Iterar por meio de propriedades de classe

118

Atualmente estou definindo todos os valores do meu objeto de classe Record.

Este é o código que estou usando para preencher o registro no momento, propriedade por propriedade.

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

Posso iterar em cada uma das propriedades dinamicamente sem codificar permanentemente todos os nomes das propriedades?

Algo assim:

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

for (int e = 0; e < propertyCount.Length - 1; e++)
{
    newRecord[fieldname] = resultItems[i - (fieldCount - e)];
}
Lucas
fonte
1
Você já experimentou o Reflection? stackoverflow.com/questions/997747/…
kol
1
por favor, dê uma olhada neste link stackoverflow.com/questions/721441/…
Enigma State
Você poderia explicar onde e como gostaria de manter o relacionamento entre uma propriedade e o índice na matriz resultItems?
Erno

Respostas:

226

Você poderia usar o Reflection para fazer isso. Pelo que entendi, você poderia enumerar as propriedades de sua classe e definir os valores. Você teria que experimentar e certificar-se de que entendeu a ordem das propriedades. Consulte esta documentação do MSDN para obter mais informações sobre essa abordagem.

Para uma dica, você poderia fazer algo como:

Record record = new Record();

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

Onde valueestá o valor que você deseja escrever (portanto, de seu resultItemsarray).

Samuel Slade
fonte
1
E se eu quiser usar property.Getvalue (someOtherClassObjectHavingExacltySameProperties) em vez de um valor ? (Eu tentei esta propriedade? .SetValue (objAppointment, property.GetValue (temp)); mas ela me dá, {"Object does not match target type."} )
Asif Mehmood
@MalikAsif Não tenho certeza se entendi totalmente, mas parece que você está tentando carregar uma propriedade de um tipo diferente. Se você postar uma pergunta no SO com um exemplo e vinculá-la aqui, vou dar uma olhada para você.
Samuel Slade
1
Este é um salva-vidas absoluto - obrigado! Estou iterando por todas as propriedades de classe para verificar se tenho um valor (antes de gravá-lo em XML)
Cordell
@Cordell, como você fez isso? Eu tentei property.GetValue () mas pede um objeto como parâmetro.
user7792598
@ user7792598 Você precisa passar o objeto do qual deseja obter o valor da propriedade. Se precisar de mais ajuda, poste outra pergunta StackOverflow
Samuel Slade
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
fonte
1
Parece bom, mas eu esperava fazer isso dinamicamente, em vez de codificar os nomes dos campos lá. Isso é possível? Obrigado
Lucas
Além disso, parece que a GetPropertypropriedade não está disponível para minha instância de classe. : /
Lucas
não, deve haver um mapeamento em algum lugar entre os índices resultItem e os nomes das propriedades.
jgauffin de
1
@Coulton Como você espera associar cada propriedade a um índice dinamicamente? Isso não é possível.
Amy de
você pode tentar, em nameof(Item.Field)vez de "itemtype"evitar a codificação permanente a partir de C # 6.0
Patrick Michaelsen
2

Sim, você poderia fazer um indexador em sua classe Record que mapeia do nome da propriedade para a propriedade correta. Isso manteria toda a ligação de nome de propriedade para propriedade em um só lugar, por exemplo:

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

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

Como alternativa, como outros mencionaram, use reflexão.

Rich O'Kelly
fonte
1

Tentei o que Samuel Slade sugeriu. Não funcionou para mim. A PropertyInfo lista estava vazia. Então, tentei o seguinte e funcionou para mim.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }
BheemaSenan
fonte
1
Será porque o seu tipo tem apenas campos, não propriedades !?
jamheadart