Получить свойства и значения от неизвестного объекта - PullRequest
134 голосов
/ 10 ноября 2010

Из мира PHP я решил попробовать C #. У меня был поиск, но я не могу найти ответ, как это сделать.

$object = new Object();

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

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

У меня есть список объектов. Объект может быть одного из трех различных типов и будет иметь набор открытых свойств. Я хочу иметь возможность получить список свойств объекта, зациклить их, а затем записать их в файл. Я думаю, что это как-то связано с отражением в c #, но для меня все это ново.

Любая помощь будет принята с благодарностью.

Ответы [ 11 ]

249 голосов
/ 10 ноября 2010

Это должно сделать это:

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
}
17 голосов
/ 10 ноября 2010

Да, Reflection - это путь.Сначала вы получите Type, который представляет тип (во время выполнения) экземпляра в списке.Вы можете сделать это, вызвав метод GetType для Object.Поскольку он относится к классу Object, он может вызываться каждым объектом в .NET, поскольку все типы являются производными от Object ( ну, технически, не все , но это не такважно здесь).

Как только у вас есть экземпляр Type, вы можете вызвать GetProperties метод , чтобы получить PropertyInfo экземпляров, которые представляют прогонинформация о свойствах в Type.

Примечание. Вы можете использовать перегрузки GetProperties, чтобы помочь классифицировать , какие свойства вы получите.

Изтам вы просто записали бы информацию в файл.

Ваш код, переведенный выше, будет:

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

Обратите внимание, что если вы хотите получить информацию о методе или поле, вы бынеобходимо вызвать одну из перегрузок методов GetMethods или GetFields соответственно.

Также обратите внимание, что одно дело перечислить членов дляфайл, но вы не должны использовать эту информацию для управления логикой на основе property sets.

Предполагая, что вы контролируете реализации типов, вы должны наследовать общий базовый класс или реализовывать общий интерфейс и выполнять вызовы для них (вы можете использовать as или is оператор, помогающий определить, с каким базовым классом / интерфейсом вы работаете во время выполнения).

Однако, если вы не управляете этими определениями типов и должныуправляйте логикой, основанной на сопоставлении с образцом, тогда все в порядке.

15 голосов
/ 11 мая 2016
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);
}
10 голосов
/ 10 ноября 2010

ну, в C # это похоже. Вот один из простейших примеров (только для открытых свойств):

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));
}
8 голосов
/ 12 августа 2013

Чтобы получить конкретное значение свойства из имени свойства

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

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

для доступа к значению свойства Name из строкового имени свойства

public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
} 
3 голосов
/ 10 января 2014

Вы можете использовать GetType - GetProperties - Linq Foreach :

obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                        //p is each PropertyInfo
                                                        DoSomething(p);
                                                    });
2 голосов
/ 10 ноября 2010

Вот что я использую для преобразования IEnumerable<T> в DataTable, который содержит столбцы, представляющие свойства T, с одной строкой для каждого элемента в 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;
}

Это «несколько» слишком сложно, но на самом деле это очень хорошо для просмотра результата, так как вы можете дать ему List<T>, например:

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

И вы получите DataTableсо структурой:

Марка (строка)
YearOfManufacture (int)

С одной строкой на элемент в вашем List<Car>

1 голос
/ 24 марта 2011

Этот пример обрезает все строковые свойства объекта.

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);
    }
}
0 голосов
/ 30 июля 2018
    public Dictionary<string, string> ToDictionary(object obj)
    {
        Dictionary<string, string> dictionary = new Dictionary<string, string>();

        Type objectType = obj.GetType();
        IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());

        foreach (PropertyInfo prop in props)
        {
            object propValue = prop.GetValue(obj, null);
            dictionary.Add(prop.Name, propValue.ToString());
        }

        return dictionary;
0 голосов
/ 27 июня 2017

Вы можете попробовать это:

string[] arr = ((IEnumerable)obj).Cast<object>()
                                 .Select(x => x.ToString())
                                 .ToArray();

Как только каждый массив реализует интерфейс IEnumerable

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...