2010-11-10 4 views
105

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

$object = new Object(); 

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

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

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

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

+7

В качестве примечания: наличие объектов различных типов в списке (без общий базовый класс или интерфейс) не является хорошим стилем программирования, по крайней мере, не в C#. –

ответ

205

Это следует сделать это:

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 
} 
+0

Откуда появляется PropertyInfo? – Jonathan

+8

@jonathan 'System.Reflection' namespace – Cocowalla

+12

Нет необходимости создавать список из массива, просто' PropertyInfo [] props = input.GetType(). GetProperties(); ' – VladL

16

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

После того, как у вас есть экземпляр Type, вы можете вызвать GetProperties method получить PropertyInfo экземпляры, которые представляют собой во время выполнения informationa о свойствах на 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, чтобы определить, какой базовый класс/интерфейс, с которым вы работаете во время выполнения).

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

2

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

С одной строке за единицу в вашем List<Car>

7

хорошо, в 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)); 
} 
1

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

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

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

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

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

obj.GetType().GetProperties().ToList().ForEach(p =>{ 
                 //p is each PropertyInfo 
                 DoSomething(p); 
                }); 
6
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); 
} 
0

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

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

string rval = serializer.Serialize(myAppObj); 
0

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

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

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

Смежные вопросы