当 属性 是另一个 class 的数组时获取 属性 的名称和值?
Get name and value of property when that property is an array of another class?
我了解如何使用反射获取给定 class 的 属性 名称和值。但是,如果 属性 是一个包含 1 个或多个另一个 class 的数组怎么办?
var person = new
{
Name = "John",
Characteristic = new[]
{
new Characteristic {Name = "Age", Value = "31"},
new Characteristic {Name = "Height", Value = "6'1""},
}
};
var properties = person.GetType().GetProperties();
foreach (var property in properties)
{
Console.WriteLine(property.Name);
Console.WriteLine(property.GetValue(person));
if (property.PropertyType.IsArray)
{
// Need to get info here! (See below)
}
}
基本上,我需要得到特定的 属性 是 Characteristic
的数组,然后是属性 Name
和 Value
,然后是这些属性的后续值特性。非常感谢!
**编辑:这是我尝试过的,但我无法获得我需要的值...此代码代替了上面的评论
foreach (var prop in property.GetType().GetProperties())
{
Console.WriteLine(prop.Name);
Console.WriteLine(prop.GetValue(property));
}
您仍然使用 GetValue()
但对于数组属性,它 returns 将数组转换为 object
因此您需要将其显式转换回 Array
if (property.PropertyType.IsArray)
{
foreach (var item in (Array)property.GetValue(person))
Console.WriteLine(item);
}
如果您还需要访问 item
的属性,请对 item
对象重复相同的 属性 scammin 例程:
if (property.PropertyType.IsArray)
{
foreach (var item in (Array)property.GetValue(person))
{
var subProperties = item.GetType().GetProperties();
foreach (var subProperty in subProperties)
{
Console.WriteLine(subProperty.Name);
Console.WriteLine(subProperty.GetValue(item));
}
}
}
更通用的版本处理任意级别的嵌套数组属性:
TraverseProps(person);
// ..................................................
static void TraverseProps(object obj, int level = 0)
{
string indent = new string(' ', level * 2);
if (obj == null)
{
Console.WriteLine(indent + "<NULL>");
return;
}
var properties = obj.GetType().GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(obj);
Console.Write(indent + property.Name + ": ");
if (property.PropertyType.IsArray)
{
Console.WriteLine(indent + "[");
int i = 0;
foreach (var item in (Array)value)
{
Console.WriteLine(indent + "item " + i + ":");
TraverseProps(item, level + 1);
i++;
}
Console.WriteLine(indent + "]");
}
else
{
Console.WriteLine(value);
}
}
}
N.B。如果对象树中存在引用循环,此函数容易无限递归。
检索数组实例后(正常使用 GetValue
),可以使用 LINQ 的 Cast() 方法将其转换为适当类型的 IEnumerable
,如下所示:
var characteristics = person.GetType().GetProperty("Characteristic", BindingFlags.Instance | BindingFlags.Public).GetValue(person, null) as System.Array;
foreach (var c in characteristics.Cast<Characteristic>())
{
Console.WriteLine("{0} = {1}", c.Name, c.Value);
}
如果您没有早期绑定访问 Characteristic
class,您也可以使用纯反射:
var characteristics = person.GetType().GetProperty("Characteristic", BindingFlags.Instance | BindingFlags.Public).GetValue(person, null) as System.Array;
foreach (var o in characteristics)
{
var name = o.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
var val = o.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
Console.WriteLine("{0} = {1}", name, val);
}
两种情况下的输出都是:
Age = 31
Height = 6'1"
这是我想出的有效方法。这将在上面的 if 语句中:
if (property.PropertyType.IsArray)
{
foreach (var item in (Array) property.GetValue(person))
{
var props = item.GetType().GetProperties();
foreach (var prop in props)
{
Console.WriteLine(prop.Name);
Console.WriteLine(prop.GetValue(item));
}
}
}
我了解如何使用反射获取给定 class 的 属性 名称和值。但是,如果 属性 是一个包含 1 个或多个另一个 class 的数组怎么办?
var person = new
{
Name = "John",
Characteristic = new[]
{
new Characteristic {Name = "Age", Value = "31"},
new Characteristic {Name = "Height", Value = "6'1""},
}
};
var properties = person.GetType().GetProperties();
foreach (var property in properties)
{
Console.WriteLine(property.Name);
Console.WriteLine(property.GetValue(person));
if (property.PropertyType.IsArray)
{
// Need to get info here! (See below)
}
}
基本上,我需要得到特定的 属性 是 Characteristic
的数组,然后是属性 Name
和 Value
,然后是这些属性的后续值特性。非常感谢!
**编辑:这是我尝试过的,但我无法获得我需要的值...此代码代替了上面的评论
foreach (var prop in property.GetType().GetProperties())
{
Console.WriteLine(prop.Name);
Console.WriteLine(prop.GetValue(property));
}
您仍然使用 GetValue()
但对于数组属性,它 returns 将数组转换为 object
因此您需要将其显式转换回 Array
if (property.PropertyType.IsArray)
{
foreach (var item in (Array)property.GetValue(person))
Console.WriteLine(item);
}
如果您还需要访问 item
的属性,请对 item
对象重复相同的 属性 scammin 例程:
if (property.PropertyType.IsArray)
{
foreach (var item in (Array)property.GetValue(person))
{
var subProperties = item.GetType().GetProperties();
foreach (var subProperty in subProperties)
{
Console.WriteLine(subProperty.Name);
Console.WriteLine(subProperty.GetValue(item));
}
}
}
更通用的版本处理任意级别的嵌套数组属性:
TraverseProps(person);
// ..................................................
static void TraverseProps(object obj, int level = 0)
{
string indent = new string(' ', level * 2);
if (obj == null)
{
Console.WriteLine(indent + "<NULL>");
return;
}
var properties = obj.GetType().GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(obj);
Console.Write(indent + property.Name + ": ");
if (property.PropertyType.IsArray)
{
Console.WriteLine(indent + "[");
int i = 0;
foreach (var item in (Array)value)
{
Console.WriteLine(indent + "item " + i + ":");
TraverseProps(item, level + 1);
i++;
}
Console.WriteLine(indent + "]");
}
else
{
Console.WriteLine(value);
}
}
}
N.B。如果对象树中存在引用循环,此函数容易无限递归。
检索数组实例后(正常使用 GetValue
),可以使用 LINQ 的 Cast() 方法将其转换为适当类型的 IEnumerable
,如下所示:
var characteristics = person.GetType().GetProperty("Characteristic", BindingFlags.Instance | BindingFlags.Public).GetValue(person, null) as System.Array;
foreach (var c in characteristics.Cast<Characteristic>())
{
Console.WriteLine("{0} = {1}", c.Name, c.Value);
}
如果您没有早期绑定访问 Characteristic
class,您也可以使用纯反射:
var characteristics = person.GetType().GetProperty("Characteristic", BindingFlags.Instance | BindingFlags.Public).GetValue(person, null) as System.Array;
foreach (var o in characteristics)
{
var name = o.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
var val = o.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
Console.WriteLine("{0} = {1}", name, val);
}
两种情况下的输出都是:
Age = 31
Height = 6'1"
这是我想出的有效方法。这将在上面的 if 语句中:
if (property.PropertyType.IsArray)
{
foreach (var item in (Array) property.GetValue(person))
{
var props = item.GetType().GetProperties();
foreach (var prop in props)
{
Console.WriteLine(prop.Name);
Console.WriteLine(prop.GetValue(item));
}
}
}