C # Itérer à travers les propriétés de classe

118

Je mets actuellement toutes les valeurs de mon objet de classe Record.

C'est le code que j'utilise pour remplir l'enregistrement pour le moment, propriété par propriété.

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

Puis-je parcourir chacune des propriétés de manière dynamique sans coder en dur tous les noms de propriété?

Quelque chose comme ça:

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

for (int e = 0; e < propertyCount.Length - 1; e++)
{
    newRecord[fieldname] = resultItems[i - (fieldCount - e)];
}
Luke
la source
1
Avez-vous essayé Reflection? stackoverflow.com/questions/997747/…
kol
1
Veuillez jeter un oeil à ce lien stackoverflow.com/questions/721441/…
Enigma State
Pourriez-vous expliquer où et comment vous voudriez maintenir la relation entre une propriété et l'index dans le tableau resultItems?
Erno

Réponses:

226

Vous pouvez éventuellement utiliser Reflection pour ce faire. Pour autant que je sache, vous pouvez énumérer les propriétés de votre classe et définir les valeurs. Vous devrez essayer ceci et vous assurer de bien comprendre l'ordre des propriétés. Reportez-vous à cette documentation MSDN pour plus d'informations sur cette approche.

Pour un indice, vous pouvez faire quelque chose comme:

Record record = new Record();

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

valueest la valeur dans laquelle vous souhaitez écrire (donc à partir de votre resultItemstableau).

Samuel Slade
la source
1
Que faire si je veux utiliser property.Getvalue (someOtherClassObjectHavingExacltySameProperties) au lieu d'une valeur ? (J'ai essayé cette propriété? .SetValue (objAppointment, property.GetValue (temp)); mais cela me donne, {"L'objet ne correspond pas au type de cible."} )
Asif Mehmood
@MalikAsif Je ne suis pas sûr de bien comprendre, mais il semble que vous essayez de charger une propriété d'un type différent. Si vous postez une question sur SO avec un exemple et le liez ici, je vais jeter un oeil pour vous.
Samuel Slade
1
C'est une bouée de sauvetage absolue - merci! J'itère toutes les propriétés de classe pour vérifier que j'ai une valeur (avant de l'écrire en XML)
Cordell
@Cordell, comment as-tu fait ça? J'ai essayé property.GetValue () mais il demande un objet comme paramètre.
user7792598
@ user7792598 Vous devez transmettre l'objet à partir duquel vous souhaitez obtenir la valeur de la propriété. Si vous avez besoin d'aide supplémentaire, postez une autre question 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
la source
1
Cela semble bon, mais j'espérais le faire de manière dynamique, plutôt que de coder en dur les noms de champ. Est-ce possible? Merci
Luke
Il semble également que la GetPropertypropriété ne soit pas disponible pour mon instance de classe. : /
Luc
non, il doit y avoir un mappage quelque part entre les index resultItem et les noms de propriété.
jgauffin
1
@Coulton Comment comptez-vous associer dynamiquement chaque propriété à un index? Ce n'est pas possible.
Amy
vous pouvez essayer nameof(Item.Field)au lieu d' "itemtype"éviter le codage en dur à partir de C # 6.0
Patrick Michaelsen
2

Oui, vous pouvez créer un indexeur sur votre classe Record qui mappe du nom de propriété à la propriété correcte. Cela conserverait toute la liaison du nom de la propriété à la propriété en un seul endroit, par exemple:

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

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

Sinon, comme d'autres l'ont mentionné, utilisez la réflexion.

Rich O'Kelly
la source
1

J'ai essayé ce que Samuel Slade a suggéré. Cela n'a pas fonctionné pour moi. La PropertyInfo liste arrivait comme vide. J'ai donc essayé ce qui suit et cela a fonctionné pour moi.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }
BheemaSenan
la source
1
Ce sera parce que votre type ne contient que des champs, pas des propriétés !?
jamheadart