关于C#:反射大师:为什么我的MethodInfo对象不相等?

Reflection Gurus: Why aren't my MethodInfo objects equal?

基本上,静态System.Linq.Expressions.Expression.Bind()方法中发生的一些内部检查在我的显然是属性的属性上说"方法不是属性访问器"。使用Reflector,我已经将导致问题的代码量减到了最小,我一辈子都无法弄明白为什么会发生这种情况。我唯一的猜测是,这与属性本身不在类上有关,但我认为这仍然有效:

我试着用最少的代码做一个小例子。下面的代码应该完整运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System;
using System.Reflection;

public class Base
{
    public virtual int Id { get; set; }
}

// As you can see, SubClass does not override the Id property of Base.
public class SubClass : Base { }

class Program
{
    static void Main(string[] args)
    {
        // Getting the property directly from the type.
        PropertyInfo propertyInfo = typeof(SubClass).GetProperty("Id");
        MethodInfo setMethod = propertyInfo.GetSetMethod();

        /*  Code from here on out is from the System.Linq.Expressions.Bind() method (the one
            that accepts a MethodInfo argument). This method causes GetProperty to be called
            and retrieve what should be the same PropertyInfo. It fails here, saying something
            along the lines of"Method is not a property accessor." which doesn't make sense. */

        PropertyInfo propertyInfo2 = GetProperty(setMethod);
    }

    private static PropertyInfo GetProperty(MethodInfo mi)
    {
        // Not sure if it matters, but declaringType here is"Base".
        Type declaringType = mi.DeclaringType;

        BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public;
        bindingAttr |= mi.IsStatic ? BindingFlags.Static : BindingFlags.Instance;

        foreach (PropertyInfo info in declaringType.GetProperties(bindingAttr))
        {
            // For the"Id" property, info.CanRead is true, but CheckMethod is false.
            if (info.CanRead && CheckMethod(mi, info.GetGetMethod(true)))
                return info;

            // For the"Id" property, info.CanWrite is true, but CheckMethod is false.
            if (info.CanWrite && CheckMethod(mi, info.GetSetMethod(true)))
                return info;
        }

        // This gets thrown after passing by the"Id" property that is the one I'm looking for.
        throw new Exception("Method is not a property accessor");
    }

    private static bool CheckMethod(MethodInfo method, MethodInfo propertyMethod)
    {
        // These are not equal, so it goes to the next check. In the debugger, they appear identical when I look through the object tree.
        if (method == propertyMethod)
            return true;

        Type declaringType = method.DeclaringType;
        return ((declaringType.IsInterface && (method.Name == propertyMethod.Name)) && (declaringType.GetMethod(method.Name) == propertyMethod));
    }
}

如果有人能帮忙,我会非常感激的!我在这一点上迷路了很多。

编辑-如果你用typeof(Base)替换typeof(SubClass),它会起作用,所以它与关系有关。我想我可以通过使用像typeof(SubClass).GetPropertyFromActualClass("Id")这样的扩展方法从根本上解决这个问题,但是我不知道如何执行这个检查。


基本类和子类的属性和方法信息确实不相等,即使子类没有自己的实现,如下所示:

1
2
3
4
5
6
7
8
var subPropertyInfo = typeof(SubClass).GetProperty("Id");
var subPropertyInfoSetter = subPropertyInfo.GetSetMethod();

var basePropertyInfo = typeof(Base).GetProperty("Id");
var basePropertyInfoSetter = basePropertyInfo.GetSetMethod();

Console.WriteLine(subPropertyInfo == basePropertyInfo);     // false
Console.WriteLine(subPropertyInfoSetter == basePropertyInfoSetter); // false

如果使用mi.reflectedType而不是mi.declaringType,则检查成功:

1
2
3
var type = subPropertyInfoSetter.ReflectedType;
Console.WriteLine(type.GetProperty("Id").GetSetMethod()
                               == subPropertyInfoSetter); // true