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

如何利用反射递归比较含多层嵌套属性的同类型对象

递归反射比较嵌套对象属性值

测试场景中需要用反射比较同类型对象,对象可能包含多层嵌套属性。示例类定义如下:

public class Connection{
    public string Ip{get; set;}
    public string Id{get; set;}
    public string Key{get; set;}
    public string Transport{get; set;}
    public Parameters ParametersObj = new Parameters();

    public class Parameters
    {
        public string AssignedName { get; set; }
        public string CategoryType { get; set; }
        public string Status { get; set; }
    }
}

现有实现仅能对比第一层属性,完全忽略嵌套对象的内部值。需要实现支持任意嵌套深度的比较逻辑,且属性存在差异时,日志要输出类似Property: Parameters.Status的完整属性路径。

现有实现代码:

bool result = true;
foreach (var objParam in firstObj.GetType().GetProperties())
{
    var value1 = objParam.GetValue(firstObj);
    var value2 = objParam.GetValue(secondObj);
    if (value1 == null || value2 == null || !value1.Equals(value2))
    {
        logger.Error("Property: " + objParam.Name);
        logger.Error("Values: " + value1?.ToString() + " and " + value2?.ToString());
        result = false;
    }
}
return result;

改进后的递归实现

可以通过递归遍历属性的方式处理嵌套对象,同时维护当前的属性路径:

private bool CompareObjects(object firstObj, object secondObj, string currentPath = "", ISet<object> comparedObjects = null)
{
    bool result = true;
    // 初始化已比较对象集合,防止循环引用导致死递归
    comparedObjects ??= new HashSet<object>();

    // 处理null情况
    if (firstObj == null && secondObj == null)
        return true;
    if (firstObj == null || secondObj == null)
    {
        logger.Error($"Property: {currentPath}");
        logger.Error($"Values: {firstObj?.ToString()} and {secondObj?.ToString()}");
        return false;
    }

    // 若对象已比较过,直接返回true(避免循环引用)
    if (!comparedObjects.Add(firstObj))
        return true;
    comparedObjects.Add(secondObj);

    Type objType = firstObj.GetType();

    // 值类型或字符串直接比较
    if (objType.IsValueType || objType == typeof(string))
    {
        if (!firstObj.Equals(secondObj))
        {
            logger.Error($"Property: {currentPath}");
            logger.Error($"Values: {firstObj.ToString()} and {secondObj.ToString()}");
            result = false;
        }
        return result;
    }

    // 遍历所有公开实例属性递归比较
    foreach (var property in objType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        string propertyPath = string.IsNullOrEmpty(currentPath) ? property.Name : $"{currentPath}.{property.Name}";
        var value1 = property.GetValue(firstObj);
        var value2 = property.GetValue(secondObj);

        if (!CompareObjects(value1, value2, propertyPath, comparedObjects))
        {
            result = false;
        }
    }

    return result;
}

关键说明

  • 递归遍历:遇到引用类型(非值类型、非字符串)时,递归调用比较方法,深入嵌套对象内部
  • 属性路径维护:通过currentPath参数拼接完整的属性层级路径,差异日志直接输出完整路径
  • null处理:单独判断两个对象的null情况,避免空引用异常
  • 循环引用防护:使用ISet<object>记录已比较过的对象,防止循环引用导致的死递归
  • 权限控制:使用BindingFlags.Public | BindingFlags.Instance确保遍历所有公开实例属性

内容的提问来源于stack exchange,提问作者Shmuel Fellous

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:35:01