14

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

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

所以基本上

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] )
4

2 回答 2

25

为了忽略继承的成员,您可以使用您已经在使用的 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 将返回一个不同的 MethodInfo GetBaseDefinition

于 2010-12-22T00:49:45.957 回答
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));
            }
        }
    }
于 2014-07-02T15:42:11.650 回答