Получить свойства и значения из неизвестного объекта
Из мира 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;