【问题标题】:Inheritance of Custom Attributes on Abstract Properties抽象属性上自定义属性的继承
【发布时间】:2011-01-31 23:29:46
【问题描述】:

我有一个自定义属性,我想将其应用于我的基本抽象类,以便在以 HTML 显示项目时跳过用户不需要查看的元素。似乎覆盖基类的属性没有继承属性。

覆盖基础属性(抽象或虚拟)是否会破坏原始属性上的属性?

来自属性类定义

[AttributeUsage(AttributeTargets.Property,
                Inherited = true,
                AllowMultiple = false)]
public class NoHtmlOutput : Attribute
{
}

来自抽象类定义

[NoHtmlOutput]
public abstract Guid UniqueID { get; set; }

来自具体的类定义

public override Guid UniqueID{ get{ return MasterId;} set{MasterId = value;}}

从类检查属性

        Type t = o.GetType();
        foreach (PropertyInfo pi in t.GetProperties())
        {
            if (pi.GetCustomAttributes(typeof(NoHtmlOutput), true).Length == 1)
                continue;
            // processing logic goes here
        }

【问题讨论】:

    标签: c# reflection attributes abstract-class


    【解决方案1】:

    您必须调用静态方法 System.Attribute.GetCustomAttributes(pi,...),而不是调用 PropertyInfo.GetCustomAttributes(...),如:

    PropertyInfo info = GetType().GetProperties();
    
    // this gets only the attributes in the derived class and ignores the 'true' parameter
    object[] DerivedAttributes = info.GetCustomAttributes(typeof(MyAttribute),true);
    
    // this gets all of the attributes up the heirarchy
    object[] InheritedAttributes = System.Attribute.GetCustomAttributes(info,typeof(MyAttribute),true);
    

    【讨论】:

    • 这应该是答案。从mytype.GetCustomAttributes() 更改为System.Attribute.GetCustomAttribute() 会使inherit 参数按预期工作。魔法!
    • 在 .NET 4.6.1 中对我不起作用。试图从实体框架动态代理的 POCO 类中获取属性(其基类型是 POCO 类)。
    • 它必须是自定义属性。不会列出 DataMemberAttribute 之类的内容。
    • @lordcheeto DataMemberAttribute 是自定义属性,继承自 System.Attribute 的任何其他属性也是如此。
    【解决方案2】:

    不,属性是继承的。

    GetCustomAttributes() 方法不查看父声明。它只查看应用于指定成员的属性。 From the docs:

    备注

    此方法忽略继承 属性和事件的参数。 搜索继承链 属性和事件的属性, 使用适当的重载 属性..::.GetCustomAttributes 方法。

    【讨论】:

    • 通过提供继承参数 pi.GetCustomAttributes(typeof(NoHtmlOutput), true) 搜索链
    • 阅读备注。 PropertyInfo.GetCustomAttributes() 忽略继承参数。
    • imo,这是一个奇怪的错误,奇怪的是它甚至在 .NET 4.5 中也没有修复。那为什么还要提供那个 bool 重载呢!
    • 有人给 Eric Lippert 打电话,弄清楚为什么这仍然是个问题。
    【解决方案3】:

    看起来只有在覆盖方法也具有属性时才会发生这种情况。

    http://msdn.microsoft.com/en-us/library/a19191fh.aspx

    但是,您可以覆盖相同类型的属性或将其他属性应用于派生组件。以下代码片段显示了一个自定义控件,该控件通过覆盖基类中应用的 BrowsableAttribute 特性来覆盖从 Control 继承的 Text 属性。 视觉基础

    Public Class MyControl
       Inherits Control
       ' The base class has [Browsable(true)] applied to the Text property.
       <Browsable(False)>  _
       Public Overrides Property [Text]() As String
          ...
       End Property 
       ...
    End Class
    

    【讨论】:

      【解决方案4】:

      这是我的尝试。这是MemberInfo 上的一个扩展方法,它手动向上遍历继承层次结构。这似乎与动态代理兼容...至少是由 Castle 创建的软管,所以我假设它与任何代理库兼容。

      public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo instance)
      {
          while (instance != null)
          {
              object[] attributes = instance.GetCustomAttributes(typeof(T), false);
              if (attributes.Length > 0)
              {
                  return attributes.Cast<T>();
              }
              Type ancestor = instance.DeclaringType.BaseType;
              if (ancestor != null)
              {
                  IEnumerable<MemberInfo> ancestormatches = ancestor.FindMembers(instance.MemberType, BindingFlags.Instance | BindingFlags.Public, 
                      (m, s) =>
                      {
                          return m.Name == (string)s;
                      }, instance.Name);
                  instance = ancestormatches.FirstOrDefault();
              }
              else
              {
                  instance = null;
              }
          }
          return new T[] { };
      }
      

      你会这样使用它。

      Type t = o.GetType();
      foreach (PropertyInfo pi in t.GetProperties())
      {
          IEnumerable<NoHtmlOutput> attributes = pi.GetCustomAttributes<NoHtmlOutput>();
          foreach (NoHtmlOutput attribute in attributes)
          {
            Console.WriteLine(attribute);
          }
      }
      

      【讨论】:

        【解决方案5】:

        你可以使用

        PropertyInfo::GetCustomAttributes<T>(true)
        

        效果很好,请参见示例: https://dotnetfiddle.net/2IhEWH

        所以,没有必要使用静态方法

        System.Attribute.GetCustomAttributes
        

        【讨论】:

          猜你喜欢
          • 2011-06-25
          • 1970-01-01
          • 2019-04-28
          • 1970-01-01
          • 2013-04-18
          • 2021-05-03
          • 1970-01-01
          • 2019-01-09
          • 1970-01-01
          相关资源
          最近更新 更多