PropertiesComparer
Comparator for two instances of the same type, comparing each property.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NUnit.Framework.Constraints.Comparers
{
[NullableContext(1)]
[Nullable(0)]
internal static class PropertiesComparer
{
public static EqualMethodResult Equal(object x, object y, ref Tolerance tolerance, ComparisonState state, NUnitEqualityComparer equalityComparer)
{
Type xType = x.GetType();
Type yType = y.GetType();
PropertiesComparerConfiguration configuration = equalityComparer.ComparePropertiesConfiguration ?? PropertiesComparerConfiguration.Default;
if (xType != yType && !configuration.AllowComparingDifferentTypes)
return EqualMethodResult.TypesNotSupported;
if (xType.IsPrimitive || yType.IsPrimitive)
return EqualMethodResult.TypesNotSupported;
PropertyInfo[] xProperties = xType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
HashSet<string> xPropertyNames = new HashSet<string>(from p in xProperties
select p.Name);
PropertyInfo[] source = xProperties;
HashSet<string> yPropertyNames = xPropertyNames;
HashSet<string> allPropertyNames = xPropertyNames;
<>c__DisplayClass0_0 <>c__DisplayClass0_;
if (xType != yType) {
source = yType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
yPropertyNames = new HashSet<string>(from p in source
select p.Name);
allPropertyNames = new HashSet<string>(xPropertyNames.Concat(yPropertyNames));
<>c__DisplayClass0_.<Equal>g__UseProperties|7(yType, yPropertyNames);
<>c__DisplayClass0_.<Equal>g__ExcludeProperties|8(yType, yPropertyNames);
}
<>c__DisplayClass0_.<Equal>g__UseProperties|7(xType, xPropertyNames);
<>c__DisplayClass0_.<Equal>g__ExcludeProperties|8(xType, xPropertyNames);
Dictionary<string, string> propertyNameMap = <>c__DisplayClass0_.<Equal>g__GetPropertyNameMap|9();
Dictionary<string, object> propertyNameToValueMap = <>c__DisplayClass0_.<Equal>g__GetPropertyToValueMap|10();
if (configuration.OnlyCompareCommonProperties && xPropertyNames != yPropertyNames) {
xPropertyNames.IntersectWith(yPropertyNames);
yPropertyNames = xPropertyNames;
}
int count = xPropertyNames.Count;
int count2 = yPropertyNames.Count;
Dictionary<string, object> dictionary = propertyNameToValueMap;
if (count != count2 + ((dictionary != null) ? dictionary.Count : 0) || xPropertyNames.Count == 0)
return EqualMethodResult.TypesNotSupported;
xProperties = (from p in xProperties
where xPropertyNames.Contains(p.Name)
select p).ToArray();
source = (from p in source
where yPropertyNames.Contains(p.Name)
select p).ToArray();
if (xProperties.Any((PropertyInfo p) => p.GetIndexParameters().Length != 0) || source.Any((PropertyInfo p) => p.GetIndexParameters().Length != 0))
return EqualMethodResult.TypesNotSupported;
ComparisonState state2 = state.PushComparison(x, y);
BitArray bitArray = new BitArray(xProperties.Length);
int num = 0;
Dictionary<string, PropertyInfo> yPropertyDictionary = source.ToDictionary((PropertyInfo x) => x.Name);
for (int i = 0; i < xProperties.Length; i++) {
(string, object, string, object) valueTuple = <>c__DisplayClass0_.<Equal>g__GetPropertyNamesAndValues|11(i);
string item = valueTuple.Item1;
object item2 = valueTuple.Item2;
string item3 = valueTuple.Item3;
object item4 = valueTuple.Item4;
Tolerance tolerance2 = tolerance;
if (tolerance.IsUnsetOrDefault) {
if ((item2 is TimeSpan || item2 is DateTime || item2 is DateTimeOffset) ? true : false)
tolerance2 = configuration.TimeSpanTolerance;
else if (Numerics.IsFloatingPointNumeric(item2)) {
tolerance2 = configuration.FloatingPointTolerance;
} else if (Numerics.IsFixedPointNumeric(item2)) {
tolerance2 = configuration.FixedPointTolerance;
}
}
switch (equalityComparer.AreEqual(item2, item4, ref tolerance2, state2)) {
case EqualMethodResult.TypesNotSupported:
case EqualMethodResult.ComparedNotEqual:
return PropertyNotEqualResult(equalityComparer, i, xType.Name, item, item2, yType.Name, item3, item4);
case EqualMethodResult.ToleranceNotSupported:
bitArray.Set(i, true);
num++;
break;
}
}
if (num == xProperties.Length)
return EqualMethodResult.ToleranceNotSupported;
if (num != 0) {
Tolerance tolerance3 = Tolerance.Exact;
for (int j = 0; j < xProperties.Length; j++) {
if (bitArray.Get(j)) {
(string, object, string, object) valueTuple2 = <>c__DisplayClass0_.<Equal>g__GetPropertyNamesAndValues|11(j);
string item5 = valueTuple2.Item1;
object item6 = valueTuple2.Item2;
string item7 = valueTuple2.Item3;
object item8 = valueTuple2.Item4;
EqualMethodResult equalMethodResult = equalityComparer.AreEqual(item6, item8, ref tolerance3, state2);
if (equalMethodResult == EqualMethodResult.ComparedNotEqual)
return PropertyNotEqualResult(equalityComparer, j, xType.Name, item5, item6, yType.Name, item7, item8);
}
}
}
return EqualMethodResult.ComparedEqual;
}
private static EqualMethodResult PropertyNotEqualResult(NUnitEqualityComparer equalityComparer, int i, string xTypeName, string xPropertyName, [Nullable(2)] object xPropertyValue, string yTypeName, string yPropertyName, [Nullable(2)] object yPropertyValue)
{
NUnitEqualityComparer.FailurePoint obj = new NUnitEqualityComparer.FailurePoint {
Position = i
};
object propertyName;
if (!(xTypeName == yTypeName)) {
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 4);
defaultInterpolatedStringHandler.AppendFormatted(xTypeName);
defaultInterpolatedStringHandler.AppendLiteral(".");
defaultInterpolatedStringHandler.AppendFormatted(xPropertyName);
defaultInterpolatedStringHandler.AppendLiteral(" => ");
defaultInterpolatedStringHandler.AppendFormatted(yTypeName);
defaultInterpolatedStringHandler.AppendLiteral(".");
defaultInterpolatedStringHandler.AppendFormatted(yPropertyName);
propertyName = defaultInterpolatedStringHandler.ToStringAndClear();
} else
propertyName = xTypeName + "." + xPropertyName;
obj.PropertyName = (string)propertyName;
obj.ExpectedHasData = true;
obj.ExpectedValue = xPropertyValue;
obj.ActualHasData = true;
obj.ActualValue = yPropertyValue;
NUnitEqualityComparer.FailurePoint item = obj;
equalityComparer.FailurePoints.Insert(0, item);
return EqualMethodResult.ComparedNotEqual;
}
}
}