您可以只遍历每个属性的属性PropertyType
,就像您为获取第一级属性所做的那样。
这是一个使用 Linq 的快速而肮脏的示例:
var properties =
from p1 in obj.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public)
from p2 in p1.PropertyType.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public).DefaultIfEmpty()
select new { OuterProperty = p1, InnerProperty = p2 };
foreach(var prop in properties)
{
Console.WriteLine(prop.OuterProperty.Name + (prop.InnerProperty != null ? "." + prop.InnerProperty.Name : ""));
}
产生输出:
CarId
Description.Chars
Description.Length
Engine.EngineId
Engine.Description
您可能只想评估给定命名空间中的类(例如,您最终不会捕获 的Length
属性Description
):
var properties =
from p1 in obj.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public)
from p2 in p1.PropertyType.Namespace == "MyNamespace"
? p1.PropertyType.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public).DefaultIfEmpty()
: new PropertyInfo[] { null }
select new { OuterProperty = p1, InnerProperty = p2 };
产生输出:
CarId
Description
Engine.EngineId
Engine.Description
或者如果你定义一个特定的属性来标记你想要遍历的属性,也许更优雅:
[AttributeUsage(AttributeTargets.Property)]
public class TraversableAttribute: Attribute { }
public class Car
{
public int CarId { get; set;}
public string Description { get; set;}
[Traversable]
public Engine Engine { get; set;}
}
...
var properties =
from p1 in obj.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public)
from p2 in p1.GetCustomAttributes(typeof(TraversableAttribute), true).Length > 0
? p1.PropertyType.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public).DefaultIfEmpty()
: new PropertyInfo[] { null }
select new { OuterProperty = p1, InnerProperty = p2 };
这将产生与前一个示例相同的输出。