比较复杂对象

时间:2013-10-15 16:02:07

标签: c# object compare

我需要编写一个比较各种类型的复杂对象的比较器,我写了一些代码,但对我来说似乎太长了,所以在两个复杂对象之间还有其他方法可以很好地进行比较吗?

我的代码:

class CompareObjOfType
{
    private static int _totalFalseCount;

    public static bool CompareObjectsOfType(Type T, object source, object target)
    {
        bool result = false;
        if ((source == null) && (target == null))
        {
            return true;
        }

        if ((source == null) ^ (target == null))
        {
            _totalFalseCount++;
            return false;
        }

        if (T.IsValueType || (T == typeof(string)))
        {
            if (T == typeof(DateTime))
            {
                if (!(((DateTime)source).ToUniversalTime().Equals(((DateTime)target).ToUniversalTime())))
                {
                    _totalFalseCount++;
                    return false;
                }
            }
            else if (T == typeof(string))
            {
                if (string.IsNullOrEmpty((string)source) ^ string.IsNullOrEmpty((string)target))
                {
                    _totalFalseCount++;
                    return false;
                }
                if (!(string.IsNullOrEmpty((string)source) && string.IsNullOrEmpty((string)target)))
                {
                    _totalFalseCount++;
                    return false;
                }

                if (!(((string)source).Equals((string)target)))
                {
                    _totalFalseCount++;
                    return false;
                }
            }
            else
            {
                if (!(source.ToString().Equals(target.ToString())))
                {
                    _totalFalseCount++;
                    return false;
                }
            }
            return true;
        }
        else
        {
            var properties = T.GetProperties();
            foreach (var property in properties)
            {
                Type propertyType = property.PropertyType;

                if (propertyType.IsArray || propertyType.IsGenericType)
                {
                    var sourceValue = property.GetValue(source);
                    var targetValue = property.GetValue(target);

                    if ((sourceValue == null) && (targetValue == null))
                    {
                        result = true;
                        continue;
                    }
                    if ((sourceValue == null) ^ (targetValue == null))
                    {
                        _totalFalseCount++;
                        result = false;
                        continue;
                    }

                    var sourceCount = ((IList)sourceValue).Count;
                    var targetCount = ((IList)targetValue).Count;

                    if (sourceCount != targetCount)
                    {
                        _totalFalseCount++;
                        result = false;
                        continue;
                    }

                    for (int i = 0; i < sourceCount; i++)
                    {
                        Type elementType = propertyType.IsArray
                                               ? propertyType.GetElementType()
                                               : propertyType.GetGenericArguments().First();
                        result = CompareObjectsOfType(elementType, ((IList)sourceValue)[i],
                                                      ((IList)targetValue)[i]);
                    }
                }
                else
                {
                    result = CompareObjectsOfType(propertyType, property.GetValue(source), property.GetValue(target));
                }
            }
        }
        return result;
    }
}

2 个答案:

答案 0 :(得分:1)

我在测试中经常使用这段代码。它绝不是完美的,但可能还不够好。注意,ignore params参数可以包含您不想比较的属性名称列表。

    public static void AssertArePropertiesEqual<T>(T expectedObj, T actualObj, params string[] ignore) where T : class
    {
        if (expectedObj != null && actualObj != null)
        {
            var type = typeof(T);
            if (type.IsPrimitive || type == typeof(string))
            {
                Assert.AreEqual(expectedObj, actualObj);
                return;
            }
            var ignoreList = new List<string>(ignore);
            foreach (var pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (ignoreList.Contains(pi.Name)) continue;
                var selfValue = type.GetProperty(pi.Name).GetValue(expectedObj, null);
                var toValue = type.GetProperty(pi.Name).GetValue(actualObj, null);
                var selfValueDate = selfValue as DateTime?;
                var toValueDate = toValue as DateTime?;

                if (selfValueDate.HasValue && toValueDate.HasValue)
                {
                    Assert.IsTrue(Math.Abs((selfValueDate.Value - toValueDate.Value).TotalSeconds) < 1,
                                  string.Format("The compare of [{0}] properties failed. Expected Date:{1}  Actual Date: {2}", pi.Name,
                                                selfValueDate, toValueDate));
                }
                else
                {
                    Assert.AreEqual(selfValue, toValue, string.Format("The compare of [{0}] properties failed.", pi.Name));
                }
            }
            return;
        }
        Assert.AreEqual(expectedObj, actualObj);
    }

答案 1 :(得分:0)

实施IComparer。在msdn上有一个例子,在万维网上有很多例子。

您需要检查的是,第一个对象在语义上是否被视为 等于大于第二个对象。

然后,您可以轻松地在LINQ查询中订购对象,或者在需要订购它们的任何地方订购。

但是,重新考虑类的设计可能会更好。

,很少需要这种广泛的比较(如代码中所示)

如果你只需要检查是否相等(不是小于大于),那么IEqualityComparer比较器就足够了,正如Kris评论的那样。