You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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所属的类型不匹配:

  1. 处理子属性(比如Prop2的Text)时,你传入的还是顶层的obj或obj.Prop1,但Text属于Type2类型,必须传入Type2的实例才能调用GetValue。
  2. 递归逻辑只拼接了属性名,没有获取当前属性对应的实例对象,导致后续GetValue的目标类型不匹配。
  3. 循环逻辑存在缺陷:遇到非原始类型就直接递归,但提前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}");
}

关键说明

  1. 传递正确的实例对象:每次处理子属性时,先通过prop.GetValue(currentObj)获取该属性对应的实例,再将这个实例传入递归方法,确保后续GetValue的目标类型匹配。
  2. 完整路径拼接:基于当前路径加上新属性名,生成层级正确的完整路径。
  3. 遍历所有分支:不再提前终止循环,确保所有子属性都被遍历,不会遗漏原始属性。
  4. 空值防护:加入currentObj == null的判断,避免空引用异常。

内容的提问来源于stack exchange,提问作者Snake Eyes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:07:47