<PackageReference Include="NUnit" Version="3.10.1" />

EquatablesComparer

Comparator for two types related by IEquatable<T>.
using NUnit.Compatibility; using System; using System.Collections.Generic; using System.Reflection; namespace NUnit.Framework.Constraints.Comparers { internal class EquatablesComparer : IChainComparer { private readonly NUnitEqualityComparer _equalityComparer; internal EquatablesComparer(NUnitEqualityComparer equalityComparer) { _equalityComparer = equalityComparer; } public bool? Equal(object x, object y, ref Tolerance tolerance, bool topLevelComparison = true) { if (_equalityComparer.CompareAsCollection & topLevelComparison) return null; Type type = x.GetType(); Type type2 = y.GetType(); MethodInfo methodInfo = FirstImplementsIEquatableOfSecond(type, type2); if ((object)methodInfo != null) return InvokeFirstIEquatableEqualsSecond(x, y, methodInfo); methodInfo = FirstImplementsIEquatableOfSecond(type2, type); if ((object)type != type2 && (object)methodInfo != null) return InvokeFirstIEquatableEqualsSecond(y, x, methodInfo); return null; } private static MethodInfo FirstImplementsIEquatableOfSecond(Type first, Type second) { KeyValuePair<Type, MethodInfo> keyValuePair = default(KeyValuePair<Type, MethodInfo>); foreach (KeyValuePair<Type, MethodInfo> equatableGenericArgument in GetEquatableGenericArguments(first)) { if (TypeExtensions.IsAssignableFrom(equatableGenericArgument.Key, second) && ((object)keyValuePair.Key == null || TypeExtensions.IsAssignableFrom(keyValuePair.Key, equatableGenericArgument.Key))) keyValuePair = equatableGenericArgument; } return keyValuePair.Value; } private static IList<KeyValuePair<Type, MethodInfo>> GetEquatableGenericArguments(Type type) { List<KeyValuePair<Type, MethodInfo>> list = new List<KeyValuePair<Type, MethodInfo>>(); Type[] interfaces = TypeExtensions.GetInterfaces(type); foreach (Type type2 in interfaces) { if (type2.GetTypeInfo().get_IsGenericType() && type2.GetGenericTypeDefinition().Equals(typeof(IEquatable<>))) list.Add(new KeyValuePair<Type, MethodInfo>(TypeExtensions.GetGenericArguments(type2)[0], TypeExtensions.GetMethod(type2, "Equals"))); } return list; } private static bool InvokeFirstIEquatableEqualsSecond(object first, object second, MethodInfo equals) { if ((object)equals == null) return false; return (bool)equals.Invoke(first, new object[1] { second }); } } }