反射:获取所有子属性

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