【问题标题】:How do I determine if a property was overridden?如何确定属性是否被覆盖?
【发布时间】:2011-05-29 03:51:31
【问题描述】:

我正在做一个项目,我需要在其中注册所有属性,因为系统非常庞大,需要大量工作来注册我想要依赖于 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])

【问题讨论】:

    标签: c# .net reflection types propertyinfo


    【解决方案1】:

    为了忽略继承的成员,您可以使用您已经在使用的 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。

    【讨论】:

    • 所以 getMethod.Dump();如果他们匹配然后注册?如果他们不忽略?
    • 抱歉,这是我在 LinqPad 中测试时遗留下来的工件。我把它改成了 Console.WriteLine。
    • 如果 getMethod.GetBaseDefinition() == getMethod 那么你知道它是原始属性,而不是被覆盖的属性。
    【解决方案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));
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多