C # Durch Klasseneigenschaften iterieren

118

Ich setze derzeit alle Werte meines Klassenobjekts Record.

Dies ist der Code, mit dem ich den Datensatz im Moment Eigenschaft für Eigenschaft auffülle.

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

Kann ich jede Eigenschaft dynamisch durchlaufen, ohne alle Eigenschaftsnamen fest zu codieren?

So etwas in der Art:

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

for (int e = 0; e < propertyCount.Length - 1; e++)
{
    newRecord[fieldname] = resultItems[i - (fieldCount - e)];
}
Luke
quelle
1
Haben Sie Reflection ausprobiert? stackoverflow.com/questions/997747/…
kol
1
Bitte werfen Sie einen Blick auf diesen Link stackoverflow.com/questions/721441/…
Enigma State
Können Sie erklären, wo und wie Sie die Beziehung zwischen einer Eigenschaft und dem Index im Array resultItems beibehalten möchten?
Erno

Antworten:

225

Sie könnten möglicherweise Reflection verwenden, um dies zu tun. Soweit ich weiß, können Sie die Eigenschaften Ihrer Klasse auflisten und die Werte festlegen. Sie müssten dies ausprobieren und sicherstellen, dass Sie die Reihenfolge der Eigenschaften verstehen. Weitere Informationen zu diesem Ansatz finden Sie in dieser MSDN-Dokumentation .

Für einen Hinweis könnten Sie möglicherweise etwas tun wie:

Record record = new Record();

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

Wo valueist der Wert, in den Sie schreiben möchten (also aus Ihrem resultItemsArray)?

Samuel Slade
quelle
1
Was ist, wenn ich property.Getvalue (someOtherClassObjectHavingExacltySameProperties) anstelle eines Werts verwenden möchte ? (Ich habe diese Eigenschaft ausprobiert? .SetValue (objAppointment, property.GetValue (temp)); aber es gibt mir, {"Objekt stimmt nicht mit Zieltyp überein ."} )
Asif Mehmood
@MalikAsif Ich bin mir nicht sicher, ob ich das vollständig verstehe, aber es hört sich so an, als würden Sie versuchen, eine Eigenschaft von einem anderen Typ zu laden. Wenn Sie eine Frage zu SO mit einem Beispiel posten und hier verlinken, werde ich nach Ihnen suchen.
Samuel Slade
1
Dies ist ein absoluter Lebensretter - danke! Ich durchlaufe alle Klasseneigenschaften, um zu überprüfen, ob ich einen Wert habe (bevor ich ihn in XML schreibe)
Cordell
@Cordell, wie hast du das gemacht? Ich habe property.GetValue () ausprobiert, aber es wird nach einem Objekt als Parameter gefragt.
user7792598
@ user7792598 Sie müssen das Objekt übergeben, von dem Sie den Eigenschaftswert erhalten möchten. Wenn Sie weitere Hilfe benötigen, posten Sie eine weitere StackOverflow-Frage
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
quelle
1
Das sieht gut aus, aber ich hatte gehofft, es dynamisch zu machen, anstatt die Feldnamen dort hart zu codieren. Ist das möglich? Vielen Dank
Luke
Es scheint auch, dass die GetPropertyEigenschaft für meine Klasseninstanz nicht verfügbar ist. : /
Luke
Nein, es muss irgendwo eine Zuordnung zwischen den resultItem-Indizes und den Eigenschaftsnamen geben.
Jgauffin
1
@Coulton Wie erwarten Sie, dass jede Eigenschaft dynamisch einem Index zugeordnet wird? Das ist doch nicht möglich.
Amy
Sie können versuchen, nameof(Item.Field)anstatt "itemtype"die harte Codierung ab C # 6.0 zu vermeiden
Patrick Michaelsen
2

Ja, Sie können einen Indexer für Ihre Record-Klasse erstellen, der den Eigenschaftsnamen der richtigen Eigenschaft zuordnet. Dies würde die gesamte Bindung von Eigenschaftsname zu Eigenschaft an einem Ort behalten, z.

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

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

Alternativ können Sie, wie bereits erwähnt, die Reflexion verwenden.

Rich O'Kelly
quelle
1

Ich habe versucht, was Samuel Slade vorgeschlagen hat. Hat bei mir nicht funktioniert. Die PropertyInfo Liste war leer. Also habe ich Folgendes versucht und es hat bei mir funktioniert.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }
BheemaSenan
quelle
1
Das liegt daran, dass Ihr Typ nur Felder enthält, keine Eigenschaften!?
Jamheadart