如何确定属性是否被覆盖?

时间:2010-12-22 00:33:24

标签: c# .net reflection types propertyinfo

我正在做一个我需要注册所有属性的项目,因为系统非常庞大,需要大量的工作来注册我想要依赖Xaml的所有属性。< / p>

目标是找到树顶部的所有属性。

所以基本上

public class A{
    public int Property1 { get; set; }
}

public class B : A{
    public int Property2 { get; set; }
    public virtual int Property3 { get; set; }
}

public class C : B{
    public override int Property3 { get; set; }
    public int Property4 { get; set; }
    public int Property5 { get; set; }
}

最终结果将是这样的

A.Property1  
B.Property2  
B.Property3  
C.Property4  
C.Property5  

如果你注意到我不想接受被覆盖的属性,因为我搜索属性的方式如果我做这样的事情

C.Property3例如它找不到它会检查C的基本类型并在那里找到它。

这是我到目前为止所做的。

public static void RegisterType( Type type )
{
    PropertyInfo[] properties = type.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.GetProperty | BindingFlags.SetProperty );

    if ( properties != null && properties.Length > 0 )
    {
        foreach ( PropertyInfo property in properties )
        {
            // if the property is an indexers then we ignore them
            if ( property.Name == "Item" && property.GetIndexParameters().Length > 0 )
                continue;

            // We don't want Arrays or Generic Property Types
            if ( (property.PropertyType.IsArray || property.PropertyType.IsGenericType) )
                continue;

            // Register Property
        }
    }
}

我想要的是以下内容:

  • 公共属性,重写,静态,私有
  • 允许获取和设置属性
  • 他们数组或通用类型
  • 它们是树的顶部,即示例中的C类是最高的(属性列表示例正是我正在寻找的)
  • 他们一个索引器属性(this [index])

3 个答案:

答案 0 :(得分:22)

为了忽略继承的成员,你可以使用你已经在做的BindingFlags.DeclaredOnly标志。

但是当重写属性时,派生类会重新声明它们。诀窍是然后查看他们的访问器方法,以确定它们是否实际上已被覆盖。

Type type = typeof(Foo);

foreach ( var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
    var getMethod = property.GetGetMethod(false);
    if (getMethod.GetBaseDefinition() == getMethod) {
        Console.WriteLine(getMethod);
    }
}

如果覆盖了该属性,则其“getter”MethodInfo将从GetBaseDefinition返回不同的MethodInfo。

答案 1 :(得分:2)

这些解决方案都不适合我的情况。我最终使用 DeclaringType 来确定定义的差异(我提供了完整的函数来给出一些上下文):

static public String GetExpandedInfo(Exception e)
{
    StringBuilder info = new StringBuilder();
    Type exceptionType = e.GetType();

    // only get properties declared in this type (i.e. not inherited from System.Exception)
    PropertyInfo[] propertyInfo = exceptionType.GetProperties(System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    if (propertyInfo.Length > 0)
    {
        // add the exception class name at the top
        info.AppendFormat("[{0}]\n", exceptionType.Name);

        foreach (PropertyInfo prop in propertyInfo)
        {
            // check the property isn't overriding a System.Exception property (i.e. Message)
            // as that is a default property accessible via the generic Exception class handlers
            var getMethod = prop.GetGetMethod(false);
            if (getMethod.GetBaseDefinition().DeclaringType == getMethod.DeclaringType)
            {
                // add the property name and it's value
                info.AppendFormat("{0}: {1}\n", prop.Name, prop.GetValue(e, null));
            }
        }
    }

答案 2 :(得分:0)

&LT;错误&gt;您可以使用property.DeclaringType来检查声明属性的类型。如果它与您当前正在反映的类型不同,则会被覆盖。&lt; /错误&gt;

有人指出,最重要的类型将重新声明该财产。没有想到这一点。我猜你必须遍历基类型然后看它们是否声明了一个具有相同名称的属性。然后,如果它在反射类型和基类中声明它被覆盖?

哦,乔希已经指出......: - )