如何使用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();
}

我正在尝试构建一种递归返回所有属性值的方法,在本例中为class c,但我想使其对任何其他类通用。

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()}");
        }
    }
}

函数返回以下结果:

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类型,而不是专门针对类ab进行检查?

我想替换以下代码行:

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

通过类似的方式:

if (property.IsClass)

我已在 Rextester

上设置了此示例

解决方法

您就在那儿-您只需要记住您是否在询问属性类型是否是一类:

if (property.PropertyType.IsClass)
,

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

但是请注意,这对于某些内置类型(例如具有string属性的Length和具有许多DateTime和{{1 }}。更糟糕的是,它的属性DayOfWeek再次是Ticks,从而创建了无限递归。因此,通过尝试一个错误,您可能必须排除某些类型,甚至实现检测递归的机制,或者至少限制最大嵌套级别。

以下是排除示例:

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 a3