¿Cómo obtener la lista de propiedades de una clase?

Respuestas:

799

Reflexión; por una instancia:

obj.GetType().GetProperties();

para un tipo:

typeof(Foo).GetProperties();

por ejemplo:

class Foo {
    public int A {get;set;}
    public string B {get;set;}
}
...
Foo foo = new Foo {A = 1, B = "abc"};
foreach(var prop in foo.GetType().GetProperties()) {
    Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(foo, null));
}

Siguiente comentario ...

  • Para obtener el valor de las propiedades estáticas, pase nullcomo primer argumento aGetValue
  • Para ver las propiedades no públicas, use (por ejemplo) GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)(que devuelve todas las propiedades de instancias públicas / privadas).
Marc Gravell
fuente
13
Para completar, también está el ComponentModel, expuesto por TypeDescriptor.GetProperties (...), que permite propiedades dinámicas de tiempo de ejecución (la reflexión se fija en tiempo de compilación).
Marc Gravell
55
Sugerencia: expanda la respuesta para cubrir propiedades protegidas / privadas / estáticas / heredadas.
Richard
1
La declaración foreach que muestra incluso funciona desde dentro de la clase de la que desea obtener las propiedades :)
halfpastfour.am
No estaba claro para mí por la forma en que se expresan los comentarios adicionales, pero el uso de las 3 banderas también obtiene sus internalpropiedades. ¿Tal vez soy el único que quedó atrapado en la sintaxis private/ non-public?
brichins
1
@Tadej ¿a qué marco te estás dirigiendo? si está utilizando .NET core, debe asegurarse de tener la using System.Reflectiondirectiva y el System.Reflection.TypeExtensionspaquete referenciados; esto proporciona la superficie API faltante a través de métodos de extensión
Marc Gravell
92

Puede usar Reflection para hacer esto: (desde mi biblioteca, esto obtiene los nombres y valores)

public static Dictionary<string, object> DictionaryFromType(object atype)
{
    if (atype == null) return new Dictionary<string, object>();
    Type t = atype.GetType();
    PropertyInfo[] props = t.GetProperties();
    Dictionary<string, object> dict = new Dictionary<string, object>();
    foreach (PropertyInfo prp in props)
    {
        object value = prp.GetValue(atype, new object[]{});
        dict.Add(prp.Name, value);
    }
    return dict;
}

Esto no funcionará para propiedades con un índice; para eso (se está volviendo difícil de manejar):

public static Dictionary<string, object> DictionaryFromType(object atype, 
     Dictionary<string, object[]> indexers)
{
    /* replace GetValue() call above with: */
    object value = prp.GetValue(atype, ((indexers.ContainsKey(prp.Name)?indexers[prp.Name]:new string[]{});
}

Además, para obtener solo propiedades públicas: ( consulte MSDN en BindingFlags enum )

/* replace */
PropertyInfo[] props = t.GetProperties();
/* with */
PropertyInfo[] props = t.GetProperties(BindingFlags.Public)

¡Esto también funciona en tipos anónimos!
Para obtener solo los nombres:

public static string[] PropertiesFromType(object atype)
{
    if (atype == null) return new string[] {};
    Type t = atype.GetType();
    PropertyInfo[] props = t.GetProperties();
    List<string> propNames = new List<string>();
    foreach (PropertyInfo prp in props)
    {
        propNames.Add(prp.Name);
    }
    return propNames.ToArray();
}

Y es casi lo mismo para los valores, o puede usar:

GetDictionaryFromType().Keys
// or
GetDictionaryFromType().Values

Pero eso es un poco más lento, me imagino.

Lucas Jones
fuente
... pero atype.GetProperty (prp.Name) va a devolver prp?
Marc Gravell
55
Con respecto al bit de propiedades públicas, de acuerdo con el artículo de MSDN vinculado: "Nota Debe especificar Instancia o Estático junto con Público o No Público o no se devolverá ningún miembro". Entonces, el código de muestra debería ser: t.GetProperties(BindingFlags.Instance | BindingFlags.Public)ot.GetProperties(BindingFlags.Static | BindingFlags.Public)
Carl Sharman
no estaba buscando el código, estaba buscando una explicación para la reflexión y ¡guau, lo aprecio mucho! Haga esto genérico y podría decir que su programa tiene superpoderes;)
Jaquarh
37
public List<string> GetPropertiesNameOfClass(object pObject)
{
    List<string> propertyList = new List<string>();
    if (pObject != null)
    {
        foreach (var prop in pObject.GetType().GetProperties())
        {
            propertyList.Add(prop.Name);
        }
    }
    return propertyList;
}

Esta función es para obtener la lista de propiedades de clase.

DDTBNT
fuente
77
Es posible que desee cambiar esto para usar yield return. No es gran cosa, pero es una mejor manera de hacerlo.
Matthew Haugen
1
Me gusta esto porque es (casi) la única respuesta que no incluye la palabra reflexión .
99
Pero esto todavía usa la reflexión, sin embargo.
GGG
2
supongo que esto es mucho mejor pObject.GetType (). GetProperties (). Seleccione (p => p.Name)
Decepcionado el
23

Podrías usar el System.Reflectionespacio de nombres con el Type.GetProperties()método:

PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public|BindingFlags.Static);
Jon Limjap
fuente
23

Basado en la respuesta de @ MarcGravell, aquí hay una versión que funciona en Unity C #.

ObjectsClass foo = this;
foreach(var prop in foo.GetType().GetProperties()) {
    Debug.Log("{0}={1}, " + prop.Name + ", " + prop.GetValue(foo, null));
}
Jacksonkr
fuente
8

Esa es mi solucion

public class MyObject
{
    public string value1 { get; set; }
    public string value2 { get; set; }

    public PropertyInfo[] GetProperties()
    {
        try
        {
            return this.GetType().GetProperties();
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }

    public PropertyInfo GetByParameterName(string ParameterName)
    {
        try
        {
            return this.GetType().GetProperties().FirstOrDefault(x => x.Name == ParameterName);
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }

    public static MyObject SetValue(MyObject obj, string parameterName,object parameterValue)
    {
        try
        {
            obj.GetType().GetProperties().FirstOrDefault(x => x.Name == parameterName).SetValue(obj, parameterValue);
            return obj;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}
Ali Osman Mollahüseyinoğlu
fuente
6

Puedes usar la reflexión.

Type typeOfMyObject = myObject.GetType();
PropertyInfo[] properties =typeOfMyObject.GetProperties();
Daan
fuente
3

También me enfrento a este tipo de requisitos.

De esta discusión obtuve otra idea,

Obj.GetType().GetProperties()[0].Name

Esto también muestra el nombre de la propiedad.

Obj.GetType().GetProperties().Count();

Esto muestra el número de propiedades.

Gracias a todos. Esta es una buena discusión.

Singaravelan
fuente
3

Aquí se mejora la respuesta de @lucasjones. Incluí mejoras mencionadas en la sección de comentarios después de su respuesta. Espero que alguien encuentre esto útil.

public static string[] GetTypePropertyNames(object classObject,  BindingFlags bindingFlags)
{
    if (classObject == null)
    {
        throw new ArgumentNullException(nameof(classObject));
    }

        var type = classObject.GetType();
        var propertyInfos = type.GetProperties(bindingFlags);

        return propertyInfos.Select(propertyInfo => propertyInfo.Name).ToArray();
 }
Imants Volkovs
fuente