如何使用 System.Reflection 确定 属性 是否是我定义的 类 之一

How to determine if a property is one of my defined classes using System.Reflection

根据这个例子:

public class a
{
    public string a1 {get; set;} = "va1";
    public int a2 {get; set;} = 20;
}

public class b
{
   public string b1 {get; set;} = "vb1";
   public int b2 {get; set;} = 40;
}

public class c
{
    public string c1 {get; set;} = "vc1";
    public int c2 {get; set;} = 60;
    public a class_a {get; set;} = new a();
    public b class_b {get; set;} = new b();
}

我正在尝试构建一个递归 returns 所有属性值的方法,在本例中为 class c,但我想让它对任何其他 class 通用].

static void GetValues(Object obj)
{
    Type t = obj.GetType();
    PropertyInfo[] properties = t.GetProperties();
    foreach (var property in properties)
    {
        if (property.PropertyType.Name == "a" || property.PropertyType.Name == "b")
        {
            Console.WriteLine($"--- Properties class: {property.PropertyType.Name} ---");
            GetValues(property.GetValue(obj, null));
        }
        else
        {
            Console.WriteLine($"Type: {property.PropertyType.Name}  {property.Name} = {property.GetValue(obj, null).ToString()}");
        }
    }
}

那个函数returns这个结果:

Type: String  c1 = vc1
Type: Int32  c2 = 60
--- Properties class: a ---
Type: String  a1 = va1
Type: Int32  a2 = 20
--- Properties class: b ---
Type: String  b1 = vb1
Type: Int32  b2 = 40

问题

有没有办法知道 属性 是否属于 class 类型,而不是专门检查 class ab

我想替换这行代码:

if (property.PropertyType.Name == "a" || property.PropertyType.Name == "b")

通过类似的方式:

if (property.IsClass)

我在 Rextester

上设置了这个例子

您就快完成了 - 您只需要记住您是否在询问 属性 类型 是否是 class:

if (property.PropertyType.IsClass)

使用反射,您可以查询任何类型的属性。请注意,结构也可能具有属性。所以递归所有类型是有意义的,而不仅仅是 类.

但请注意,这对于某些 built-in 类型可能没有意义,例如 string 具有 Length 属性 和 DateTime 具有许多属性,例如 DayOfWeekTicks。更糟糕的是,它有一个 属性 Date 又是一个 DateTime,创建了一个无限递归。因此,通过试错,您可能必须排除某些类型,甚至实施检测递归的机制或至少限制嵌套的最大级别。

这里有一个排除的例子:

private static readonly HashSet<Type> ExcludedTypes = 
    new HashSet<Type> { typeof(string), typeof(DateTime) };

static void GetValues(Object obj, int level)
{
    Type t = obj.GetType();
    PropertyInfo[] properties = t.GetProperties();
    foreach (var property in properties) {
        if (property.GetIndexParameters().Length == 0) { // Exclude indexers
            Console.Write(new string(' ', 4 * level));
            Type pt = property.PropertyType;
            object value = property.GetValue(obj, null);
            Console.WriteLine($"{pt.Name} {property.Name} = {value}");
            if (value != null && !ExcludedTypes.Contains(pt)) {
                GetValues(value, level + 1);
            }
        }
    }
}

调用结果GetValues(new c(), 0);
(我添加了 DateTime a3Point b3 属性以使其更有趣):

String c1 = vc1
Int32 c2 = 60
a class_a = WhosebugTests3.RecurseProperties+a
    String a1 = va1
    Int32 a2 = 20
    DateTime a3 = 23.10.2020 16:55:01
b class_b = WhosebugTests3.RecurseProperties+b
    String b1 = vb1
    Int32 b2 = 40
    Point b3 = {X=7,Y=3}
        Boolean IsEmpty = False
        Int32 X = 7
        Int32 Y = 3