web-dev-qa-db-fra.com

Obtenir les propriétés et les valeurs d'un objet inconnu

Du monde de PHP j'ai décidé d'essayer C #. J'ai fait une recherche, mais je n'arrive pas à trouver la réponse pour savoir comment faire l'équivalent.

$object = new Object();

$vars = get_class_vars(get_class($object));

foreach($vars as $var)
{
    doSomething($object->$var);
}

J'ai essentiellement une liste d'un objet. L'objet peut être l'un des trois types différents et aura un ensemble de propriétés publiques. Je veux pouvoir obtenir une liste des propriétés de l'objet, les parcourir en boucle, puis les écrire dans un fichier. Je pense que cela a quelque chose à voir avec la réflexion c # mais c'est tout nouveau pour moi.

Toute aide serait grandement appréciée.

135
m4rc

Cela devrait le faire:

Type myType = myObject.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

foreach (PropertyInfo prop in props)
{
    object propValue = prop.GetValue(myObject, null);

    // Do something with propValue
}
251
Cocowalla

Oui, la réflexion serait la voie à suivre. Tout d'abord, vous obtiendrez le Type qui représente le type (au moment de l'exécution) de l'instance dans la liste. Vous pouvez le faire en appelant la méthode GetType SUR Object . Comme il se trouve dans la classe Object, il est appelable par tous les objets dans .NET, tous les types dérivant de Object ( ). techniquement, pas tout , mais ce n’est pas important ici).

Une fois que vous avez l’instance Type, vous pouvez appeler la méthode GetProperties pour obtenir les instances PropertyInfo qui représentent les informations d’exécutiona à propos de les propriétés sur le Type.

Notez que vous pouvez utiliser les surcharges de GetProperties pour vous aider à classer les propriétés que vous récupérez.

À partir de là, il vous suffirait d'écrire les informations dans un fichier.

Votre code ci-dessus, traduit, serait:

// The instance, it can be of any type.
object o = <some object>;

// Get the type.
Type type = o.GetType();

// Get all public instance properties.
// Use the override if you want to classify
// which properties to return.
foreach (PropertyInfo info in type.GetProperties())
{
    // Do something with the property info.
    DoSomething(info);
}

Notez que si vous souhaitez des informations sur les méthodes ou les champs, vous devez appeler l’une des surcharges de GetMethods ou GetFields . méthodes respectivement.

Notez également que le fait de répertorier les membres dans un fichier est une chose, mais vous ne devez pas utiliser ces informations pour gérer la logique en fonction de jeux de propriétés.

En supposant que vous ayez le contrôle sur les implémentations des types, vous devez dériver d'une classe de base commune ou implémenter une interface commune et effectuer les appels sur celles-ci (vous pouvez utiliser le as ou is opérateur permettant de déterminer la classe/l'interface de base avec laquelle vous travaillez au moment de l'exécution).

Cependant, si vous ne contrôlez pas ces définitions de type et devez piloter une logique basée sur la correspondance de modèle, c'est très bien.

17
casperOne
void Test(){
    var obj = new{a="aaa", b="bbb"};

    var val_a = obj.GetValObjDy("a"); //="aaa"
    var val_b = obj.GetValObjDy("b"); //="bbb"
}
//create in a static class
static public object GetValObjDy(this object obj, string propertyName)
{            
     return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}
16
Vo Van Khoa

eh bien, en C #, c'est pareil. Voici l'un des exemples les plus simples (uniquement pour les propriétés publiques):

var someObject = new { .../*properties*/... };
var propertyInfos = someObject.GetType().GetProperties();
foreach (PropertyInfo pInfo in PropertyInfos)
{
    string propertyName = pInfo.Name; //gets the name of the property
    doSomething(pInfo.GetValue(someObject,null));
}
10
AlexanderMP

Pour obtenir une valeur de propriété spécifique à partir du nom de la propriété

public class Bike{
public string Name {get;set;}
}

Bike b = new Bike {Name = "MyBike"};

pour accéder à la valeur de la propriété Name à partir du nom de chaîne de la propriété

public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
} 
9
RAJ

Vous pouvez utiliser GetType - GetProperties - Linq Foreach:

obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                        //p is each PropertyInfo
                                                        DoSomething(p);
                                                    });
3
Antonio DB

Voici quelque chose que j'utilise pour transformer un IEnumerable<T> en un DataTable contenant des colonnes représentant les propriétés de T, avec une ligne pour chaque élément du IEnumerable:

public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
    var table = CreateDataTableForPropertiesOfType<T>();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (var item in items)
    {
        var dr = table.NewRow();
        for (int property = 0; property < table.Columns.Count; property++)
        {
            if (piT[property].CanRead)
            {
                var value = piT[property].GetValue(item, null);
                if (piT[property].PropertyType.IsGenericType)
                {
                    if (value == null)
                    {
                        dr[property] = DBNull.Value;
                    }
                    else
                    {
                        dr[property] = piT[property].GetValue(item, null);
                    }
                }
                else
                {
                    dr[property] = piT[property].GetValue(item, null);
                }
            }
        }
        table.Rows.Add(dr);
    }
    return table;
}

public static DataTable CreateDataTableForPropertiesOfType<T>()
{
    DataTable dt = new DataTable();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (PropertyInfo pi in piT)
    {
        Type propertyType = null;
        if (pi.PropertyType.IsGenericType)
        {
            propertyType = pi.PropertyType.GetGenericArguments()[0];
        }
        else
        {
            propertyType = pi.PropertyType;
        }
        DataColumn dc = new DataColumn(pi.Name, propertyType);

        if (pi.CanRead)
        {
            dt.Columns.Add(dc);
        }
    }
    return dt;
}

C'est "un peu" compliqué, mais c'est en fait assez bon pour voir le résultat, car vous pouvez lui donner un List<T> de, par exemple:

public class Car
{
    string Make { get; set; }
    int YearOfManufacture {get; set; }
}

Et vous recevrez un DataTable avec la structure:

Marque (chaîne)
Année de fabrication (int)

Avec une ligne par article dans votre List<Car>

2
Rob

Cet exemple limite toutes les propriétés de chaîne d'un objet.

public static void TrimModelProperties(Type type, object obj)
{
    var propertyInfoArray = type.GetProperties(
                                    BindingFlags.Public | 
                                    BindingFlags.Instance);
    foreach (var propertyInfo in propertyInfoArray)
    {
        var propValue = propertyInfo.GetValue(obj, null);
        if (propValue == null) 
            continue;
        if (propValue.GetType().Name == "String")
            propertyInfo.SetValue(
                             obj, 
                             ((string)propValue).Trim(), 
                             null);
    }
}
1
Brian Paske

Je n'ai pas trouvé que cela fonctionne, par exemple les objets Application. J'ai cependant eu du succès avec

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

string rval = serializer.Serialize(myAppObj);
0
jcsubmit