如何读取对象关联列表CourseEvents的属性名与属性值?
问题描述
现有以下C#模型类:
public class Course { public Guid Id { get; set; } public string Title { get; set; } public IList<CourseEvent> CourseEvents { get; set; } } public class CourseEvent { public Guid Id { get; set; } public Guid CourseId { get; set; } public DateTime StartDate { get; set; } }
以及一个读取对象属性名与值的方法:
private void WritePropertyNames(object obj) { foreach (var item in obj.GetType().GetProperties()) { Console.WriteLine(item.Name + " => " + item.GetValue(obj, null)); } }
调用示例:
var course = new Course { Title = "My course", CourseEvents = new List<CourseEvent>() { new() { StartDate = DateTime.Today }, new() { StartDate = DateTime.Today.AddDays(-1) } } }; WritePropertyNames(course);
但该方法无法获取关联列表CourseEvents中元素的属性名与值。我尝试了以下错误代码,请问正确实现方式是什么?
foreach (var item2 in obj.GetType().GetProperty("CourseEvents").GetType().GetProperties()) { Console.WriteLine(item2.Name + " => " + item2.GetValue(obj, null)); }
正确实现方式
错误原因分析
你写的错误代码存在两个核心问题:
obj.GetType().GetProperty("CourseEvents").GetType()获取的是PropertyInfo的类型,而非列表元素CourseEvent的类型,遍历的是属性信息类的属性,不是目标元素的属性。- 未获取到列表的实际实例,也没有遍历列表中的单个元素。
递归遍历实现
要解决这个问题,需要通过递归遍历处理嵌套结构:如果对象属性是集合/列表类型,就逐个取出元素再遍历其属性;如果是普通对象则直接遍历属性。修改后的方法如下:
private void WritePropertyNames(object obj, int indentLevel = 0) { if (obj == null) return; // 生成缩进,让嵌套结构的输出更清晰 string indent = new string(' ', indentLevel * 4); Type objType = obj.GetType(); // 处理集合类型(排除字符串,因为字符串也实现IEnumerable但无需遍历字符) if (obj is IEnumerable enumerable && !(obj is string)) { int index = 0; foreach (var element in enumerable) { Console.WriteLine($"{indent}[{index}] ----------------"); WritePropertyNames(element, indentLevel + 1); index++; } return; } // 遍历普通对象的属性 foreach (var prop in objType.GetProperties()) { object value = prop.GetValue(obj, null); Console.WriteLine($"{indent}{prop.Name} => {value}"); // 递归处理复杂对象/集合(排除值类型和字符串) if (value != null && !(value is string) && !value.GetType().IsValueType) { WritePropertyNames(value, indentLevel + 1); } } }
调用示例
使用原course对象调用修改后的方法:
var course = new Course { Title = "My course", CourseEvents = new List<CourseEvent>() { new() { StartDate = DateTime.Today }, new() { StartDate = DateTime.Today.AddDays(-1) } } }; WritePropertyNames(course);
输出示例
Id => 00000000-0000-0000-0000-000000000000 Title => My course CourseEvents => System.Collections.Generic.List`1[CourseEvent] [0] ---------------- Id => 00000000-0000-0000-0000-000000000000 CourseId => 00000000-0000-0000-0000-000000000000 StartDate => 2024/5/20 00:00:00 [1] ---------------- Id => 00000000-0000-0000-0000-000000000000 CourseId => 00000000-0000-0000-0000-000000000000 StartDate => 2024/5/19 00:00:00
关键说明
- 增加
indentLevel参数控制输出缩进,让嵌套层级更直观。 - 排除字符串类型的集合判断,避免无意义的字符遍历。
- 递归处理所有复杂对象和集合,确保所有层级的属性都被遍历到。
内容的提问来源于stack exchange,提问作者Mads
相关产品推荐
相关产品推荐

