反射:获取所有子属性
Reflection: Get all subproperties
我有一个包含对象的列表,每个对象都包含多种类型的许多属性,并且每个属性还包含子属性。
我需要通过反射获取所有属性并将它们存储在一个 PropertyInfo[] ...
这甚至可以通过反射实现吗?我真的需要通过反思来做...
没有 "sub properties" 这样的东西 - 属性属于特定类型,可以具有特定类型的值(即 属性 类型的子类),并且该类型可以有自己的属性。
您可以为此使用递归:
List<PropertyInfo> properties = new List<PropertyInfo>();
foreach (object obj in myList)
{
properties.AddRange(GetDeepProperties(obj, ...));
}
PropertyInfo[] array = properties.ToArray();
...
IEnumerable<PropertyInfo> GetDeepProperties(object obj, BindingFlags flags)
{
// Get properties of the current object
foreach (PropertyInfo property in obj.GetType().GetProperties(flags))
{
yield return property;
object propertyValue = property.GetValue(obj, null);
if (propertyValue == null)
{
// Property is null, but can still get properties of the PropertyType
foreach (PropertyInfo subProperty in property.PropertyType.GetProperties(flags))
{
yield return subProperty;
}
}
else
{
// Get properties of the value assiged to the property
foreach (PropertyInfo subProperty = GetDeepProperties(propertyValue))
{
yield return subProperty;
}
}
}
}
以上代码只是一个例子:
- 我没有尝试过,甚至没有编译过
- 如果此 "property tree" 中的某处对象指向彼此
,您将得到一个 WhosebugException
- 它错过了 null 检查和异常处理(属性 getter 可以抛出异常)
- 它忽略索引属性的存在
我不知道你想用这个数组做什么 - 对创建每个 PropertyInfo
的对象的引用丢失了,所以你不能再获取或设置它们的值。
示例:
class Program
{
static void Main(string[] args)
{
PropertyInfo[] result = GetAllPropertyInfos(typeof(Example)).ToArray(); ;
foreach (string property in result.Select(p => string.Format("{0} : {1}",p.Name,p.PropertyType.Name)))
{
Console.WriteLine(property);
}
}
static IEnumerable<PropertyInfo> GetAllPropertyInfos(Type type)
{
List<PropertyInfo> result = new List<PropertyInfo>();
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
result.Add(propertyInfo);
result.AddRange(GetAllPropertyInfos(propertyInfo.PropertyType));
}
return result;
}
}
class Example
{
public AnotherExample AProperty { get; set; }
public int AnotherProperty { get; set; }
}
class AnotherExample
{
public int YetAnotherProperty { get; set; }
}
输出:
AProperty : AnotherExample
YetAnotherProperty : Int32
AnotherProperty : Int32
我有一个包含对象的列表,每个对象都包含多种类型的许多属性,并且每个属性还包含子属性。
我需要通过反射获取所有属性并将它们存储在一个 PropertyInfo[] ...
这甚至可以通过反射实现吗?我真的需要通过反思来做...
没有 "sub properties" 这样的东西 - 属性属于特定类型,可以具有特定类型的值(即 属性 类型的子类),并且该类型可以有自己的属性。
您可以为此使用递归:
List<PropertyInfo> properties = new List<PropertyInfo>();
foreach (object obj in myList)
{
properties.AddRange(GetDeepProperties(obj, ...));
}
PropertyInfo[] array = properties.ToArray();
...
IEnumerable<PropertyInfo> GetDeepProperties(object obj, BindingFlags flags)
{
// Get properties of the current object
foreach (PropertyInfo property in obj.GetType().GetProperties(flags))
{
yield return property;
object propertyValue = property.GetValue(obj, null);
if (propertyValue == null)
{
// Property is null, but can still get properties of the PropertyType
foreach (PropertyInfo subProperty in property.PropertyType.GetProperties(flags))
{
yield return subProperty;
}
}
else
{
// Get properties of the value assiged to the property
foreach (PropertyInfo subProperty = GetDeepProperties(propertyValue))
{
yield return subProperty;
}
}
}
}
以上代码只是一个例子:
- 我没有尝试过,甚至没有编译过
- 如果此 "property tree" 中的某处对象指向彼此 ,您将得到一个
- 它错过了 null 检查和异常处理(属性 getter 可以抛出异常)
- 它忽略索引属性的存在
WhosebugException
我不知道你想用这个数组做什么 - 对创建每个 PropertyInfo
的对象的引用丢失了,所以你不能再获取或设置它们的值。
示例:
class Program
{
static void Main(string[] args)
{
PropertyInfo[] result = GetAllPropertyInfos(typeof(Example)).ToArray(); ;
foreach (string property in result.Select(p => string.Format("{0} : {1}",p.Name,p.PropertyType.Name)))
{
Console.WriteLine(property);
}
}
static IEnumerable<PropertyInfo> GetAllPropertyInfos(Type type)
{
List<PropertyInfo> result = new List<PropertyInfo>();
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
result.Add(propertyInfo);
result.AddRange(GetAllPropertyInfos(propertyInfo.PropertyType));
}
return result;
}
}
class Example
{
public AnotherExample AProperty { get; set; }
public int AnotherProperty { get; set; }
}
class AnotherExample
{
public int YetAnotherProperty { get; set; }
}
输出:
AProperty : AnotherExample
YetAnotherProperty : Int32
AnotherProperty : Int32