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

EquatablesComparer

Comparator for two types related by IEquatable<T>.
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 (methodInfo != (MethodInfo)null) return InvokeFirstIEquatableEqualsSecond(x, y, methodInfo); methodInfo = FirstImplementsIEquatableOfSecond(type2, type); if (type != type2 && methodInfo != (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 (equatableGenericArgument.Key.IsAssignableFrom(second) && (keyValuePair.Key == (Type)null || keyValuePair.Key.IsAssignableFrom(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 = type.GetInterfaces(); foreach (Type type2 in interfaces) { if (type2.GetTypeInfo().IsGenericType && type2.GetGenericTypeDefinition().Equals(typeof(IEquatable<>))) list.Add(new KeyValuePair<Type, MethodInfo>(type2.GetGenericArguments()[0], type2.GetMethod("Equals"))); } return list; } private static bool InvokeFirstIEquatableEqualsSecond(object first, object second, MethodInfo equals) { if (!(equals != (MethodInfo)null)) return false; return (bool)equals.Invoke(first, new object[1] { second }); } } }