如何使用 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 a
或 b
?
我想替换这行代码:
if (property.PropertyType.Name == "a" || property.PropertyType.Name == "b")
通过类似的方式:
if (property.IsClass)
我在 Rextester
上设置了这个例子
您就快完成了 - 您只需要记住您是否在询问 属性 类型 是否是 class:
if (property.PropertyType.IsClass)
使用反射,您可以查询任何类型的属性。请注意,结构也可能具有属性。所以递归所有类型是有意义的,而不仅仅是 类.
但请注意,这对于某些 built-in 类型可能没有意义,例如 string
具有 Length
属性 和 DateTime
具有许多属性,例如 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
和 Point 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
根据这个例子:
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 a
或 b
?
我想替换这行代码:
if (property.PropertyType.Name == "a" || property.PropertyType.Name == "b")
通过类似的方式:
if (property.IsClass)
我在 Rextester
上设置了这个例子您就快完成了 - 您只需要记住您是否在询问 属性 类型 是否是 class:
if (property.PropertyType.IsClass)
使用反射,您可以查询任何类型的属性。请注意,结构也可能具有属性。所以递归所有类型是有意义的,而不仅仅是 类.
但请注意,这对于某些 built-in 类型可能没有意义,例如 string
具有 Length
属性 和 DateTime
具有许多属性,例如 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
和 Point 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