标识覆盖基本属性或实现接口的属性

时间:2010-07-20 17:21:54

标签: c# .net reflection .net-3.5

我得到了:

  • 一个类“T”,它实现了用我感兴趣的属性修饰的属性。

  • PropertyInfop”表示属于(1)I实现的接口“T”的属性,(2)基类“BT继承自,或(3)类T本身。

我需要在T中定义(或继承)属性的属性,即使p的DeclaringType是T实现的接口或类T继承自。因此,我需要一种方法从p转到PropertyInfo上实际存在的T。因此似乎有3种情况:

  1. p.DeclaringType == typeof(T)

    这是一个微不足道的案例。我可以遍历T的属性,直到找到匹配项。例如:

    return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    .FirstOrDefault(property => property == p)
    
  2. p.DeclaringType == typeof(I)其中IT实现的接口

    这更复杂。我发现我可以使用InterfaceMapping在p中查找T的相应实现。这看起来有点像hackish,但这里有效:

    if (p.DeclaringType.IsInterface &&
        typeof(T).GetInterfaces().Contains(p.DeclaringType))
    {
        InterfaceMapping map = typeof(T).GetInterfaceMap(p.DeclaringType);
        MethodInfo getMethod = p.GetGetMethod();
        for (int i = 0; i < map.InterfaceMethods.Length; i++)
        {
            if (map.InterfaceMethods[i] == getMethod)
            {
                MethodInfo target = map.TargetMethods[i];
                return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .FirstOrDefault(property => property.GetGetMethod() == target);
            }
        }
    }
    
  3. p.DeclaringType == typeof(B)其中BT继承自

    的类

    我还没有弄清楚如何识别T上覆盖p基类T中定义的虚拟属性B的属性。< / p>

  4. 所以我的问题是

    • 案例3 中如何找到覆盖PropertyInfo上的T属性的p上的B
    • 有没有更好的方法来做这三个?也许是一种统一这三种情况的方法。

2 个答案:

答案 0 :(得分:1)

我认为你错过了一个案例:T可能只是从B继承了属性,而没有覆盖它(除非你确定在你的特定场景中不会发生这种情况) )。

无论如何,您只需要使用typeof(T).GetProperty按名称搜索属性,因为在给定的类中不能有2个具有相同名称的属性(与可能有多个重载的方法不同)。但是,您需要注意使用T修饰符B 隐藏继承自new的属性的情况。要处理这种情况,您可以检查属性的getter方法的Attributes(使用GetGetMethod获得):如果存在NewSlot标志,则会隐藏继承的getter。

答案 1 :(得分:0)

我找到了回答案例3 的方法。关键是MethodInfo.GetBaseDefinition

if (typeof(T).IsSubclassOf(p.DeclaringType))
{
    MethodInfo baseDefinition = p.GetGetMethod().GetBaseDefinition();
    return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    .FirstOrDefault(property => property.GetGetMethod().GetBaseDefinition() == baseDefinition);
}

但是,这仅适用于已在T上覆盖的属性。

编辑:

通过比较以下内容,T是否已覆盖或未覆盖属性无关紧要:

property.GetGetMethod().GetBaseDefinition().MetadataToken == baseDefinition.MetadataToken