【问题标题】:Do custom attribute classes inherit the "Inherited" AttributeUsage flag?自定义属性类是否继承“继承的”AttributeUsage 标志?
【发布时间】:2013-02-19 10:39:57
【问题描述】:

考虑以下场景:

  • 基属性类BaseAttribute 有一个AttributeUsageAttribute,指定它不可继承(Inherited = False)。
  • 派生属性类DerivedAttribute 继承自该基属性类。
  • 基域类Base 应用了派生属性。
  • 从基域类继承的域类Derived 被要求为其自定义 属性,包括继承的属性 (inherit: true)。

下面是对应的代码:

using System;
using System.Linq;

namespace ConsoleApplication26
{
  class Program
  {
    static void Main ()
    {
      var attributes = typeof (Derived).GetCustomAttributes (true);
      foreach (var attribute in attributes)
      {
        Console.WriteLine (
            "{0}: Inherited = {1}",
            attribute.GetType().Name,
            attribute.GetType().GetCustomAttributes (typeof (AttributeUsageAttribute), true).Cast<AttributeUsageAttribute>().Single().Inherited);
      }
    }
  }

  [AttributeUsage (AttributeTargets.All, Inherited = false)]
  public class BaseAttribute : Attribute
  {
  }

  public class DerivedAttribute : BaseAttribute
  {
  }

  [Derived]
  public class Base
  {
  }

  public class Derived : Base
  {
  }
}

在这种情况下,GetCustomAttributes API 返回DerivedAttribute 类的实例。我原以为它不会返回该实例,因为http://msdn.microsoft.com/en-us/library/system.attributeusageattribute.aspxAttributeUsageAttribute 本身是可继承的。

现在,这是一个错误,还是预期/记录在某处?

注(2013-02-20):实验表明BaseAttribute类的AttributeTargets部分确实被DerivedAttribute类继承。例如,当我将BaseAttribute 上的允许目标更改为AttributeTargets.Method 时,C# 编译器将不允许我将DerivedAttribute 应用于一个类。因此,Inherited = false 部分不被DerivedAttribute 继承是没有意义的,因此我倾向于认为GetCustomAttributes 的实现中存在错误。

【问题讨论】:

  • 不确定我是否看到了问题。如果您不想看到该属性,则必须将 false 传递给 GetCustomAttributes() 方法。
  • 是的,我知道我可以通过false。但是,我试图理解为什么我在传递 true 时得到了属性,即使 Derived 类不应该继承该属性。我希望有人指出一些文档或规范来解释我所看到的。
  • 看起来 AttributeUsageAttribute Inherited 标志没有被继承,尽管人们期望它是因为 AttributeUsageAttribute 用 [AttributeUsage(AttributeTargets.Class, Inherited = true)] 装饰。
  • 我们遇到了与 AuthorizeAttribute 类似的情况。我们有几个相互继承的控制器从一个名为“OurAuthorizeAttribute”的属性中获得越来越严格的权限。当我们没有将 AuthorizeAttribute 上的 AttributeUsage 显式添加到我们的自定义属性时,AuthorizeCore() 不会堆叠。当我们添加它时,它的行为符合预期。在我们的例子中,“正如所料”只是属性继承了它们的基本属性用法。我们有针对这种行为的单元测试,我们将尝试发布。 AttributeUsage.Inherited 属性被忽略。

标签: c# reflection custom-attributes


【解决方案1】:

根据 .NET 4.0 中的元数据,AttributeUsageAttribute 类标记为[AttributeUsage(AttributeTargets.Class, Inherited = true)]。因此,如果您的属性类(BaseAttribute,在您的示例中)应用了AttributeUsageAttribute(所有Attribute 类都应该这样做,但是如果它们没有破坏任何东西,请参见下文),那么从BaseAttribute 派生的任何类都应该继承应用于它的AttributeUsage 属性。

您的Derived 类从Base 继承DerivedAttribute,因为DerivedAttribute 没有应用自己的AttributeUsageAttribute,因此反射API 依赖于BaseAttribute 的属性。现在,从BaseAttribute 类中删除AttributeUsageAttribute,你会得到相同的结果,因为基类System.Attribute[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] 标记。因此,任何属性类都将继承此属性,除非您指定其他属性。

哇,这些都是复杂的段落。属性上的属性使阅读变得繁重:P

【讨论】:

  • 但是我的BaseAttribute 被声明为是可继承的。那么,如果反射 API 依赖于 BaseAttribute 声明的属性用法,为什么 DerivedAttribute 是可继承的?
  • 嗯...好吧,那么...好问题!
猜你喜欢
  • 2011-06-25
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 2011-01-31
  • 2016-11-13
  • 2018-09-09
相关资源
最近更新 更多