比较复杂对象
本文关键字:对象 复杂 比较 | 更新日期: 2023-09-27 18:35:22
我需要写一个比较器来比较各种类型的复杂对象,我写了一些代码,但对我来说似乎太长了,那么有两个复杂对象之间有没有其他很好的比较方法?
我的代码:
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;
}
}
我在测试中经常使用此代码。它绝不完美,但可能足够好。 请注意,忽略参数可以包含您不想比较的属性名称列表。
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);
}
实现 IComparer。在msdn上有一个示例,在万维网上也有很多示例。
您需要检查的只是第一个对象在语义上是否被视为小于、等于或大于第二个对象。
然后,可以轻松地在 LINQ 查询中或需要对对象进行排序的任何位置对对象进行排序。
但是,最好重新考虑类的设计。很少需要这种广泛的比较(如在您的代码中)。
如果你只需要检查相等性(不小于或大于),那么一个IEqualityComparer比较器就足够了,正如Kris所评论的那样。