C#如何从嵌套对象中获取属性全路径及对应值?
获取对象原始属性完整路径及对应值时触发类型不匹配异常
我有一个对象,想要获取其所有原始属性的完整路径及对应值,对象结构如下:
Type1 Prop1 |_ Type2 Prop2 |_ string Text |_ Type3 Prop3 |_ Type4 Prop4 |_ int Number ...
我目前尝试的代码如下:
调用逻辑:
var props = obj.Prop1.GetType().GetProperties(); foreach (var prop in props) { var name = GetData(prop, obj); // 将结果添加到列表/字典并处理 }
判断原始类型的方法:
static bool IsPrimitive(Type t) { return t.IsPrimitive || t == typeof(string); }
递归获取属性的方法:
static KeyValuePair<string,object> GetData(PropertyInfo property, object reference) { if (IsPrimitive(property.PropertyType)) { return new KeyValuePair<string, object>(property.Name, property.GetValue(reference,null)); } var props = property.PropertyType.GetProperties(); var name = property.Name; object value = null; foreach (var p in props) { var kvp = GetData(p, reference); name += $".{kvp.Key}."; value = kvp.Value; if (IsPrimitive(p.PropertyType)) { break; } } return new KeyValuePair<string, object>(name.Trim('.'), value); }
问题在于调用GetValue(reference, null)时出现异常:
'Object does not match target type.'
我尝试过传入GetData(prop, obj);以及GetData(prop, obj.Prop1);,但都会触发相同的错误。
预期输出应为:
Prop1.Prop2.Text 及其对应值 Prop1.Prop3.Prop4.Number 及其对应值
请问我哪里出错了?
错误原因
核心问题是递归调用时传入的reference对象类型和当前PropertyInfo所属的类型不匹配:
- 处理子属性(比如
Prop2的Text)时,你传入的还是顶层的obj或obj.Prop1,但Text属于Type2类型,必须传入Type2的实例才能调用GetValue。 - 递归逻辑只拼接了属性名,没有获取当前属性对应的实例对象,导致后续
GetValue的目标类型不匹配。 - 循环逻辑存在缺陷:遇到非原始类型就直接递归,但提前
break会漏掉分支,且名称拼接方式会产生多余的分隔符或截断路径。
修正后的代码
以下是修复后的实现,会递归遍历所有原始属性,生成正确的完整路径和对应值:
// 存储结果的字典,键为完整属性路径,值为对应属性值 var result = new Dictionary<string, object>(); // 从Prop1开始遍历,初始路径设为"Prop1" TraverseProperties(obj.Prop1, "Prop1", result); // 递归遍历属性的核心方法 static void TraverseProperties(object currentObj, string currentPath, Dictionary<string, object> result) { if (currentObj == null) return; var props = currentObj.GetType().GetProperties(); foreach (var prop in props) { var propValue = prop.GetValue(currentObj); var fullPath = $"{currentPath}.{prop.Name}"; if (IsPrimitive(prop.PropertyType)) { // 原始类型直接加入结果集 result.Add(fullPath, propValue); } else { // 非原始类型继续递归遍历子属性 TraverseProperties(propValue, fullPath, result); } } } // 保留原有的原始类型判断方法 static bool IsPrimitive(Type t) { return t.IsPrimitive || t == typeof(string); }
调用示例
// 假设obj是Type1的实例 var result = new Dictionary<string, object>(); TraverseProperties(obj.Prop1, "Prop1", result); // 输出所有结果 foreach (var kvp in result) { Console.WriteLine($"{kvp.Key} 及其对应值: {kvp.Value}"); }
关键说明
- 传递正确的实例对象:每次处理子属性时,先通过
prop.GetValue(currentObj)获取该属性对应的实例,再将这个实例传入递归方法,确保后续GetValue的目标类型匹配。 - 完整路径拼接:基于当前路径加上新属性名,生成层级正确的完整路径。
- 遍历所有分支:不再提前终止循环,确保所有子属性都被遍历,不会遗漏原始属性。
- 空值防护:加入
currentObj == null的判断,避免空引用异常。
内容的提问来源于stack exchange,提问作者Snake Eyes
相关产品推荐
相关产品推荐

