C # Iteruj po właściwościach klasy


118

Obecnie ustawiam wszystkie wartości mojego obiektu klasy Record.

To jest kod, którego używam do zapełnienia rekordu w tej chwili, właściwość według właściwości.

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

Czy mogę dynamicznie iterować każdą z właściwości bez twardego kodowania wszystkich nazw właściwości?

Coś takiego:

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

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

1
Czy próbowałeś Reflection? stackoverflow.com/questions/997747/…
kol

1
proszę spojrzeć na ten link stackoverflow.com/questions/721441/…
Enigma State

Czy możesz wyjaśnić, gdzie i jak chcesz zachować relację między właściwością a indeksem w tablicy resultItems?
Erno,

Odpowiedzi:


226

Możesz do tego użyć Reflection. O ile rozumiem, możesz wyliczyć właściwości swojej klasy i ustawić wartości. Musisz jednak to wypróbować i upewnić się, że rozumiesz kolejność właściwości. Więcej informacji na temat tego podejścia można znaleźć w tej dokumentacji MSDN .

Dla podpowiedzi możesz zrobić coś takiego:

Record record = new Record();

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

Gdzie valuejest wartość, którą chcesz zapisać (czyli z twojej resultItemstablicy).


1
A co jeśli chcę użyć property.Getvalue (someOtherClassObjectHavingExacltySameProperties) zamiast wartości ? (Próbowałem tej właściwości? .SetValue (objAppointment, property.GetValue (temp)); ale daje mi {"Obiekt nie pasuje do typu docelowego."} )
Asif Mehmood

@MalikAsif Nie jestem pewien, czy w pełni rozumiem, ale wygląda na to, że próbujesz załadować właściwość z innego typu. Jeśli opublikujesz pytanie na SO z przykładem i połączysz je tutaj, poszukam Cię.
Samuel Slade

1
To absolutny ratownik - dziękuję! Iteruję przez wszystkie właściwości klasy, aby sprawdzić, czy mam wartość (przed zapisaniem jej do XML)
Cordell

@Cordell, jak to zrobiłeś? Próbowałem property.GetValue (), ale prosi o obiekt jako parametr.
user7792598

@ user7792598 Musisz przekazać obiekt, z którego chcesz pobrać wartość właściwości. Jeśli potrzebujesz dalszej pomocy, opublikuj kolejne pytanie dotyczące 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]);
}

1
Wygląda to dobrze, ale miałem nadzieję, że zrobię to dynamicznie, zamiast na sztywno kodować nazwy pól w tym miejscu. czy to możliwe? Dzięki
Łukasz

Wydaje się również, że GetPropertywłaściwość nie jest dostępna dla mojej instancji klasy. : /
Łukasz

nie, gdzieś pomiędzy indeksami resultItem a nazwami właściwości musi znajdować się mapowanie.
jgauffin

1
@Coulton Jak chcesz dynamicznie kojarzyć każdą właściwość z indeksem? To nie jest możliwe.
Amy

możesz spróbować nameof(Item.Field)zamiast tego "itemtype"unikać twardego kodowania od C # 6.0
Patrick Michaelsen

2

Tak, można utworzyć indeksator w klasie Record, który odwzorowuje nazwę właściwości na właściwą właściwość. Pozwoliłoby to zachować całe powiązanie od nazwy właściwości do właściwości w jednym miejscu, np .:

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

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

Alternatywnie, jak wspominali inni, użyj refleksji.


1

Wypróbowałem to, co zasugerował Samuel Slade . Nie działa dla mnie. PropertyInfo Lista wracał jako pusty. Więc wypróbowałem następujące i zadziałało.

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

1
Dzieje się tak, ponieważ Twój typ zawiera tylko pola, a nie właściwości !?
jamheadart
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.