1018 votes

Obtenir la valeur de la propriété de chaîne à l'aide de la réflexion en C#

Je suis en train de mettre en œuvre la transformation de Données à l'aide de Réflexion1 exemple dans mon code.

L' GetSourceValue de la fonction de commutateur de la comparaison de divers types, mais je veux supprimer ces types de propriétés et ont GetSourceValue obtenir la valeur de la propriété en utilisant une seule chaîne en tant que paramètre. Je veux passer d'une classe et de la propriété dans la chaîne et régler la valeur de la propriété.

Est-ce possible?

1Web version Archive de blog original

1970voto

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

Bien sûr, vous voulez ajouter de la validation et de la chose, mais c'est l'essentiel.

225voto

jheddings Points 10510

Comment quelque chose comme cela:

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 à l'aide d'une chaîne unique, 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 comme les méthodes statiques ou des extensions.

89voto

Eduardo Cuomo Points 1433

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:

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

47voto

Fredou Points 9553

que penser de l'utilisation de la CallByName de la visualbasic espace de noms? qui est la réflexion.

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

et puis

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

34voto

AlexD Points 51

Gteat réponse par jheddings, je voudrais l'améliorer, afin de permettre le référencement de l'ensemble des tableaux ou des collections d'objets, de sorte que propertyName pourrait être propriété1.propriété2[X].propriété3:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X