声明类型的MethodInfo相等性

12

我需要检查两个MethodInfo之间是否相等。实际上它们是完全相同的MethodInfo,唯一不同的是ReflectedType(也就是DeclaringType是相同的,这些方法实际上应该具有相同的主体)。有许多方法可以做到这一点,但我正在寻找最有效的方法。

现在我已经有了以下代码:

    public static bool AreMethodsEqualForDeclaringType(this MethodInfo first, MethodInfo second)
    {
        first = first.ReflectedType == first.DeclaringType ? first : first.DeclaringType.GetMethod(first.Name, first.GetParameters().Select(p => p.ParameterType).ToArray());
        second = second.ReflectedType == second.DeclaringType ? second : second.DeclaringType.GetMethod(second.Name, second.GetParameters().Select(p => p.ParameterType).ToArray());
        return first == second;
    }

这个方法有点耗费资源,所以我在想是否有更好的方法...

我应该比较这两个方法的具体实现吗?例如:

first.GetMethodBody() == second.GetMethodBody()

谢谢。


为什么不能直接比较声明类型而不将其与反射类型进行比较?我也想知道为什么需要这样做。 - jgauffin
1
肯定可以只比较声明类型,但那会更费资源,因为它需要调用GetParameters(),而如果ReflectedTypes相等,我就可以进行常规的相等性检查。 - Jeff
1
我需要这样做是因为我有由EntityFramework在运行时创建的代理类,我正在进行一些反射操作。 - Jeff
4个回答

4
我将作为问题的答案留下来...
需要注意的一点是:
first.GetMethodBody() == second.GetMethodBody()

无法正常工作...目前我找到的唯一答案是:

public static bool AreMethodsEqualForDeclaringType(this MethodInfo first, MethodInfo second)
{
    first = first.ReflectedType == first.DeclaringType ? first : first.DeclaringType.GetMethod(first.Name, first.GetParameters().Select(p => p.ParameterType).ToArray());
    second = second.ReflectedType == second.DeclaringType ? second : second.DeclaringType.GetMethod(second.Name, second.GetParameters().Select(p => p.ParameterType).ToArray());
    return first == second;
}

方法体中有一个 byte[],它是方法体的 IL,您可以逐字节比较这些字节,而不仅仅使用“==”。 - justin.m.chase
@Jeff。我知道我晚了十年左右,但是...你还在成功地使用这段代码吗?我需要类似的东西,但不想重新发明轮子。Ayende在这个帖子上有一些内容,你肯定看过。感谢任何反馈。干杯 - Berryl

2
会不会比较MetadataTokenModule有帮助呢?
MetadataToken的文档描述它为:“一个值,与Module结合使用,可以唯一地标识元数据元素。”
到目前为止,我已经发现它适用于比较除ReflectedType MemberInfo实例之外的相等情况。但我没有测试过泛型方法定义等情况。

谢谢,但这只是在它不起作用的特定情况下。 - Jeff

1

当您尝试将类和接口方法相等时,此代码将起作用:

    static bool EquelMethods(MethodInfo method1, MethodInfo method2)
    {
        var find = method1.DeclaringType.GetMethod(method2.Name, method2.GetParameters().Select(p => p.ParameterType).ToArray());
        return find != null;
    }

0
这里的其他答案在处理泛型时会失败。
特别是当以下情况之一成立时,它们将出现问题:
  1. 当具有相同参数但仅在泛型计数方面不同的不同重载时
  2. 当将泛型方法定义与构造方法进行比较时
  3. 当比较使用不同类型参数构造的构造泛型方法时
这里有一个解决方案,涵盖了所有这些情况:
static bool IsEqual(MethodInfo methodInfo, MethodInfo other)
{
    if (methodInfo.ReflectedType == other.ReflectedType) return methodInfo == other;
    if (methodInfo.DeclaringType != other.DeclaringType) return false;

    return methodInfo.Name == other.Name
        && methodInfo.GetParameters().Select(p => p.ParameterType)
               .SequenceEqual(other.GetParameters().Select(p => p.ParameterType))
        && methodInfo.GetGenericArguments()
               .SequenceEqual(other.GetGenericArguments());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接