我需要编写一个比较各种类型的复杂对象的比较器,我写了一些代码,但对我来说似乎太长了,所以在两个复杂对象之间还有其他方法可以很好地进行比较吗?
我的代码:
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;
}
}
答案 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评论的那样。