C # Iterar a través de las propiedades de la clase

118

Actualmente estoy configurando todos los valores de mi objeto de clase Record.

Este es el código que estoy usando para completar el registro en este momento, propiedad por propiedad.

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

¿Puedo recorrer cada una de las propiedades dinámicamente sin codificar todos los nombres de las propiedades?

Algo así:

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

for (int e = 0; e < propertyCount.Length - 1; e++)
{
    newRecord[fieldname] = resultItems[i - (fieldCount - e)];
}
Luke
fuente
1
¿Has probado Reflection? stackoverflow.com/questions/997747/…
kol
1
Por favor, eche un vistazo a este enlace stackoverflow.com/questions/721441/…
Enigma State
¿Podría explicar dónde y cómo le gustaría mantener la relación entre una propiedad y el índice en la matriz resultItems?
Erno

Respuestas:

226

Posiblemente podría usar Reflection para hacer esto. Por lo que yo entiendo, podría enumerar las propiedades de su clase y establecer los valores. Sin embargo, tendría que probar esto y asegurarse de comprender el orden de las propiedades. Consulte esta documentación de MSDN para obtener más información sobre este enfoque.

Para una pista, posiblemente podría hacer algo como:

Record record = new Record();

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

¿Dónde valueestá el valor que desea escribir (es decir, de su resultItemsmatriz)?

Samuel Slade
fuente
1
¿Qué sucede si quiero usar property.Getvalue (someOtherClassObjectHavingExacltySameProperties) en lugar de un valor ? ( ¿Probé esta propiedad? .SetValue (objAppointment, property.GetValue (temp)); pero me da, {"El objeto no coincide con el tipo de destino."} )
Asif Mehmood
@MalikAsif No estoy seguro de haberlo entendido completamente, pero parece que está intentando cargar una propiedad de un tipo diferente. Si publica una pregunta en SO con un ejemplo y la vincula aquí, lo buscaré.
Samuel Slade
1
Este es un salvavidas absoluto, ¡gracias! Estoy iterando a través de todas las propiedades de la clase para verificar que tengo un valor (antes de escribirlo en XML)
Cordell
@Cordell, ¿cómo hiciste eso? Intenté property.GetValue () pero solicita un objeto como parámetro.
user7792598
@ user7792598 Debe pasar el objeto del que desea obtener el valor de la propiedad. Si necesita más ayuda, publique otra pregunta de 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
fuente
1
Esto se ve bien, pero esperaba hacerlo de forma dinámica, en lugar de codificar los nombres de campo allí. es posible? Gracias
Lucas
También parece que la GetPropertypropiedad no está disponible para mi instancia de clase. : /
Lucas
no, es necesario que haya una asignación en algún lugar entre los índices de resultItem y los nombres de propiedad.
jgauffin
1
@Coulton ¿Cómo espera asociar cada propiedad a un índice de forma dinámica? Eso no es posible.
Amy
puede intentar en nameof(Item.Field)lugar de "itemtype"evitar la codificación rígida a partir de C # 6.0
Patrick Michaelsen
2

Sí, puede crear un indexador en su clase Record que se asigne desde el nombre de la propiedad a la propiedad correcta. Esto mantendría toda la vinculación del nombre de la propiedad a la propiedad en un solo lugar, por ejemplo:

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

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

Alternativamente, como han mencionado otros, use la reflexión.

Rich O'Kelly
fuente
1

Probé lo que sugirió Samuel Slade . No funcionó para mí. La PropertyInfo lista venía vacía. Entonces, probé lo siguiente y funcionó para mí.

    Type type = typeof(Record);
    FieldInfo[] properties = type.GetFields();
    foreach (FieldInfo property in properties) {
       Debug.LogError(property.Name);
    }
BheemaSenan
fuente
1
¿¡Eso será porque su tipo solo tiene campos, no propiedades !?
jamheadart