反射大师:为什么我的 MethodInfo 对象不相等? [英] Reflection Gurus: Why aren't my MethodInfo objects equal?

查看:61
本文介绍了反射大师:为什么我的 MethodInfo 对象不相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,静态 System.Linq.Expressions.Expression.Bind() 方法中发生的一些内部检查在我的属性上说方法不是属性访问器",这显然是一个属性.使用 Reflector,我最大限度地减少了导致问题的代码量,而且我一生都无法弄清楚为什么会发生这种情况.我唯一的猜测是它与属性不在类本身上的事实有关,但我认为这应该仍然有效:

Basically, some internal check that happens in the static System.Linq.Expressions.Expression.Bind() method says "Method is not a property accessor" on my property that is clearly a property. Using Reflector, I've minimized the amount of code causing the problem, and I can't for the life of me figure out why this would happen. My only guess is that it has something to do with the fact that the property isn't on the class itself, but I would think this should still work:

我试图用尽可能少的代码制作一个小例子.下面的代码应该完整运行.

I've tried to make a small example with the least amount of code possible. The code below should run in its entirety.

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

如果有人能提供帮助,我将不胜感激!在这一点上,我非常迷茫.

If anyone could help I would greatly appreciate it! I'm very much lost at this point.

编辑 - 如果您将 typeof(SubClass) 替换为 typeof(Base),它会起作用,因此它与该关系有关.我想我可以通过创建像 typeof(SubClass).GetPropertyFromActualClass("Id") 这样的扩展方法来从根本上解决这个问题,但我不确定如何执行该检查.

Edit - If you substitute typeof(SubClass) with typeof(Base), it works, so it's something related to that relationship. I guess I could cut the issue off at the root by making an extension method like typeof(SubClass).GetPropertyFromActualClass("Id") but I'm not sure how to perform that check.

推荐答案

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

The property and method infos of Base and SubClass are indeed not equal, even if SubClass has no own implementation, as can be seen here:

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,则检查成功:

If you use mi.ReflectedType instead of mi.DeclaringType, the check succeeds:

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

这篇关于反射大师:为什么我的 MethodInfo 对象不相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆