Question Récupère la valeur de la propriété de la chaîne en utilisant la réflexion en C #


J'essaie de mettre en œuvre le Transformation de données utilisant Reflection1 exemple dans mon code.

le GetSourceValue fonction a un commutateur comparant différents types, mais je veux supprimer ces types et propriétés et avoir GetSourceValue obtenir la valeur de la propriété en utilisant seulement une seule chaîne comme paramètre. Je veux passer une classe et une propriété dans la chaîne et résoudre la valeur de la propriété.

Est-ce possible?

1  Version Web Archive de l'article de blog original


680
2017-07-28 21:58


origine


Réponses:


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

Bien sûr, vous voudrez ajouter une validation, et cetera, mais c'est l'essentiel.


1361
2017-07-28 22:02



Que diriez-vous quelque chose comme ça:

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;
}

Cela vous permettra de descendre dans les propriétés en utilisant une seule chaîne, comme ceci:

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

Vous pouvez utiliser ces méthodes en tant que méthodes ou extensions statiques.


170
2017-12-23 18:55



Ajouter à n'importe quel 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; }
}

Ensuite, vous pouvez utiliser comme:

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

44
2017-07-23 19:58



Qu'en est-il d'utiliser le CallByName du Microsoft.VisualBasic espace de noms (Microsoft.VisualBasic.dll)? Il utilise la réflexion pour obtenir les propriétés, les champs et les méthodes des objets normaux, des objets COM et même des objets dynamiques.

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

et alors

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

38
2017-12-23 19:24



Bonne réponse de jheddings. Je voudrais l'améliorer en permettant le référencement des tableaux agrégés ou des collections d'objets, de sorte que propertyName puisse être property1.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



À propos de la discussion sur les propriétés imbriquées, vous pouvez éviter toutes les choses de réflexion si vous utilisez le DataBinder.Eval Method (Object, String) comme ci-dessous:

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

Bien sûr, vous devrez ajouter une référence à System.Web assemblage, mais ce n'est probablement pas une grosse affaire.


6
2017-07-29 14:19



Si j'utilise le code de Ed S. Je reçois

'ReflectionExtensions.GetProperty (Type, chaîne)' est inaccessible en raison de son niveau de protection

Il paraît que GetProperty() n'est pas disponible dans Xamarin.Forms. TargetFrameworkProfile est Profile7 dans ma bibliothèque de classes portable (.NET Framework 4.5, Windows 8, ASP.NET Core 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS Classic).

Maintenant, j'ai trouvé une solution de travail:

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;
}

La source


6
2017-09-06 09:18



Utilisation de PropertyInfo du System.Reflection espace de nommage. La réflexion se compile bien, peu importe la propriété à laquelle nous essayons d'accéder. L'erreur apparaîtra pendant l'exécution.

    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;
    }

Cela fonctionne correctement pour obtenir la propriété Location d'un objet

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

Nous obtiendrons l'emplacement: {X = 71, Y = 27} Nous pouvons également renvoyer location.X ou location.Y de la même manière.


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;
    }

C'est un moyen d'obtenir toutes les propriétés avec leurs valeurs dans une liste.


3
2018-01-06 13:46