Pregunta Obtenga el valor de la propiedad de la cadena usando la reflexión en C #


Estoy tratando de implementar el Transformación de datos usando Reflexión1 ejemplo en mi código.

los GetSourceValue función tiene un interruptor que compara varios tipos, pero quiero eliminar estos tipos y propiedades y tener GetSourceValue obtener el valor de la propiedad utilizando solo una cadena como parámetro. Quiero pasar una clase y una propiedad en la cadena y resolver el valor de la propiedad.

es posible?

1  Versión del archivo web de la publicación original del blog


680
2017-07-28 21:58


origen


Respuestas:


 public static object GetPropValue(object src, string propName)
 {
     return src.GetType().GetProperty(propName).GetValue(src, null);
 }

Por supuesto, querrá agregar validación y otras cosas, pero esa es la esencia de esto.


1361
2017-07-28 22:02



Qué tal algo como esto:

public static Object GetPropValue(this Object obj, String name) {
    foreach (String part in name.Split('.')) {
        if (obj == null) { return null; }

        Type type = obj.GetType();
        PropertyInfo info = type.GetProperty(part);
        if (info == null) { return null; }

        obj = info.GetValue(obj, null);
    }
    return obj;
}

public static T GetPropValue<T>(this Object obj, String name) {
    Object retval = GetPropValue(obj, name);
    if (retval == null) { return default(T); }

    // throws InvalidCastException if types are incompatible
    return (T) retval;
}

Esto te permitirá descender a las propiedades usando una sola cuerda, como esta:

DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");

Puede utilizar estos métodos como métodos estáticos o extensiones.


170
2017-12-23 18:55



Agregar a cualquier Class:

public class Foo
{
    public object this[string propertyName]
    {
        get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
        set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
    }

    public string Bar { get; set; }
}

Entonces, puedes usar como:

Foo f = new Foo();
// Set
f["Bar"] = "asdf";
// Get
string s = (string)f["Bar"];

44
2017-07-23 19:58



¿Qué hay de usar el CallByName del Microsoft.VisualBasic espacio de nombres (Microsoft.VisualBasic.dll)? Utiliza la reflexión para obtener propiedades, campos y métodos de objetos normales, objetos COM e incluso objetos dinámicos.

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;

y entonces

Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();

38
2017-12-23 19:24



Gran respuesta por jheddings. Me gustaría mejorarlo permitiendo la referencia de matrices agregadas o colecciones de objetos, de modo que propertyName podría ser propiedad1.property2 [X] .property3:

    public static object GetPropertyValue(object srcobj, string propertyName)
    {
        if (srcobj == null)
            return null;

        object obj = srcobj;

        // Split property name to parts (propertyName could be hierarchical, like obj.subobj.subobj.property
        string[] propertyNameParts = propertyName.Split('.');

        foreach (string propertyNamePart in propertyNameParts)
        {
            if (obj == null)    return null;

            // propertyNamePart could contain reference to specific 
            // element (by index) inside a collection
            if (!propertyNamePart.Contains("["))
            {
                PropertyInfo pi = obj.GetType().GetProperty(propertyNamePart);
                if (pi == null) return null;
                obj = pi.GetValue(obj, null);
            }
            else
            {   // propertyNamePart is areference to specific element 
                // (by index) inside a collection
                // like AggregatedCollection[123]
                //   get collection name and element index
                int indexStart = propertyNamePart.IndexOf("[")+1;
                string collectionPropertyName = propertyNamePart.Substring(0, indexStart-1);
                int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length-indexStart-1));
                //   get collection object
                PropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName);
                if (pi == null) return null;
                object unknownCollection = pi.GetValue(obj, null);
                //   try to process the collection as array
                if (unknownCollection.GetType().IsArray)
                {
                    object[] collectionAsArray = unknownCollection as Array[];
                    obj = collectionAsArray[collectionElementIndex];
                }
                else
                {
                    //   try to process the collection as IList
                    System.Collections.IList collectionAsList = unknownCollection as System.Collections.IList;
                    if (collectionAsList != null)
                    {
                        obj = collectionAsList[collectionElementIndex];
                    }
                    else
                    {
                        // ??? Unsupported collection type
                    }
                }
            }
        }

        return obj;
    }

23
2018-02-14 09:18



Acerca de la discusión de propiedades anidadas, puede evitar todas las reflexiones si usa el DataBinder.Eval Method (Object, String) como a continuación:

var value = DataBinder.Eval(DateTime.Now, "TimeOfDay.Hours");

Por supuesto, deberá agregar una referencia al System.Web asamblea, pero esto probablemente no es un gran problema.


6
2017-07-29 14:19



Si uso el código de Ed S. yo obtengo

'ReflectionExtensions.GetProperty (Type, string)' es inaccesible debido a su nivel de protección

Parece que GetProperty() no está disponible en Xamarin.Forms. TargetFrameworkProfile es Profile7 en mi Biblioteca de clases portátil (.NET Framework 4.5, Windows 8, ASP.NET Core 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS Classic).

Ahora encontré una solución de trabajo:

using System.Linq;
using System.Reflection;

public static object GetPropValue(object source, string propertyName)
{
    var property = source.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase));
    if(property != null)
    {
        return property.GetValue(source);
    }
    return null;
}

Fuente


6
2017-09-06 09:18



Usando PropertyInfo de System.Reflection espacio de nombres La reflexión se compila muy bien sin importar a qué propiedad intentemos acceder. El error surgirá durante el tiempo de ejecución.

    public static object GetObjProperty(object obj, string property)
    {
        Type t = obj.GetType();
        PropertyInfo p = t.GetProperty("Location");
        Point location = (Point)p.GetValue(obj, null);
        return location;
    }

Funciona bien para obtener la propiedad Location de un objeto

Label1.Text = GetObjProperty(button1, "Location").ToString();

Obtendremos la Ubicación: {X = 71, Y = 27} También podemos devolver location.X o location.Y de la misma manera.


4
2017-11-04 06:06



public static List<KeyValuePair<string, string>> GetProperties(object item) //where T : class
    {
        var result = new List<KeyValuePair<string, string>>();
        if (item != null)
        {
            var type = item.GetType();
            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var pi in properties)
            {
                var selfValue = type.GetProperty(pi.Name).GetValue(item, null);
                if (selfValue != null)
                {
                    result.Add(new KeyValuePair<string, string>(pi.Name, selfValue.ToString()));
                }
                else
                {
                    result.Add(new KeyValuePair<string, string>(pi.Name, null));
                }
            }
        }
        return result;
    }

Esta es una forma de obtener todas las propiedades con sus valores en una lista.


3
2018-01-06 13:46



El método para llamar ha cambiado en .NET Standard (a partir de 1.6). También podemos usar el operador condicional nulo de C # 6.

using System.Reflection; 
public static object GetPropValue(object src, string propName)
{
    return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}

3
2018-05-24 15:06