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
});
}
}
}