public class MethodSignatureComparer : IEqualityComparer<MethodInfo>
{
public static readonly MethodSignatureComparer Instance = new MethodSignatureComparer();
public bool Equals(MethodInfo x, MethodInfo y)
{
if (x == null && y == null)
{
return true;
}
if (x == null || y == null)
{
return false;
}
return EqualNames(x, y) &&
EqualGenericParameters(x, y) &&
EqualSignatureTypes(x.ReturnType, y.ReturnType) &&
EqualParameters(x, y);
}
private bool EqualNames(MethodInfo x, MethodInfo y)
{
return x.Name == y.Name;
}
public bool EqualGenericParameters(MethodInfo x, MethodInfo y)
{
if (x.IsGenericMethod != y.IsGenericMethod)
{
return false;
}
if (x.IsGenericMethod)
{
Type[] xArgs = x.GetGenericArguments();
Type[] yArgs = y.GetGenericArguments();
if (xArgs.Length != yArgs.Length)
{
return false;
}
for (int i = 0; i < xArgs.Length; ++i)
{
if (xArgs[i].IsGenericParameter != yArgs[i].IsGenericParameter)
{
return false;
}
if (!xArgs[i].IsGenericParameter && !xArgs[i].Equals(yArgs[i]))
{
return false;
}
}
}
return true;
}
public bool EqualParameters(MethodInfo x, MethodInfo y)
{
ParameterInfo[] xArgs = x.GetParameters();
ParameterInfo[] yArgs = y.GetParameters();
if (xArgs.Length != yArgs.Length)
{
return false;
}
for (int i = 0; i < xArgs.Length; ++i)
{
if (!EqualSignatureTypes(xArgs[i].ParameterType, yArgs[i].ParameterType))
{
return false;
}
}
return true;
}
public bool EqualSignatureTypes(Type x, Type y)
{
if (x.IsGenericParameter != y.IsGenericParameter)
{
return false;
}
if (x.IsGenericParameter)
{
if (x.GenericParameterPosition != y.GenericParameterPosition)
{
return false;
}
}
else
{
if (!x.Equals(y))
{
return false;
}
}
return true;
}
public int GetHashCode(MethodInfo obj)
{
return obj.Name.GetHashCode() ^ obj.GetParameters().Length;
}
}