Получить свойства и значения из неизвестного объекта

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

$object = new Object();

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

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

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

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

Ответ 1

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

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
}

Ответ 2

Да, рефлексией будет путь. Во-первых, вы получите 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 соответственно.

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

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

Здесь я использую для преобразования 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>

Ответ 8

В этом примере обрезаются все строковые свойства объекта.

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

Ответ 9

Я не нашел, чтобы это работало, скажем, приложения. Однако у меня был успех с

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

string rval = serializer.Serialize(myAppObj);

Ответ 10

Однолинейное решение с использованием Linq...

var obj = new {Property1: 1, Property2: 2};
var property1 = obj.GetType().GetProperties().First(o => o.Name == "Property1").GetValue(obj , null);

Ответ 11

Вы можете попробовать следующее:

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

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

Ответ 12

    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;