§ ITPOW >> 文档 >> C#

C# 中的特性(Attributes)-2

作者:子非鱼 来源:子非鱼的 blog 日期:2009-1-31

定义或控制自定义Attribute的用法

AttributeUsage 类是另一预定义类(译者注:attribute类本身用这个atrribute System.AttributeUsage来标记),它将帮助我们控制我们自定义attribute的用法,这就是,我们能为自定义的attribute类定义attributes。

它描述了一个自定义attribute类能被怎样使用。

AttributeUsage 提供三个属性,我们能将它们放置到我们的自定义attribute类上, 第一个特性是:

ValidOn

通过这个属性,我们能指定我们的自定义attribute可以放置在哪些语言元素之上。这组我们能把自定义attribute类放置其上的语言元素被放在枚举器AttributeTargets 中。我们可以使用bitwise(译者注:这个词不知道怎么翻译好,但他的意思是可以这么用:[AttributeUsage((AttributeTargets)4, AllowMultiple = false, Inherited = false )],4代表就是“class”元素,其它诸如1代表“assembly”,16383代表“all”等等)或者”.”操做符绑定几个AttributeTargets 值。(译者注:默认值为AttributeTargets.All)

AllowMultiple

该属性标识我们的自定义attribte能在同一语言元素上使用多次。(译者注:该属性为bool类型,默认值为false,意思就是该自定义attribute在同一语言元素上只能使用一次)

Inherited

我们可以使用该属性来控制我们的自定义attribute类的继承规则。该属性标识我们的自定义attribute是否可以由派生类继承。((译者注:该属性为bool类型,默认值为false,意思是不能继承)

让我们来做点实际的东西吧,我们将把AttributeUsage attribute 放置在我们的help attribute 上并在它的帮助下,我们来控制help attribute的用法。

using System;
 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false )]
public class HelpAttribute : Attribute
{
    public HelpAttribute(String Description_in)
    {
        this.description = Description_in;
    }
   
    protected String description;
   
    public String Description
    {
        get
        {
            return this.description;
        }
    }
}

首先我们注意 AttributeTargets.Class. 它规定这个help attribute 只能放置在语言元素”class”之上。这就意味着,下面的代码将会产生一个错误。

AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.

现在试着把它绑定到方法。

[Help("this is a do-nothing class")]
public class AnyClass
{
    [Help("this is a do-nothing method")]    //error
    public void AnyMethod()
    {
    }
}

我们可以使用 AttributeTargets.All 来允许 Help attribute 可以放置在任何预定义的语言元素上,那些可能的语言元素如下:

  • Assembly
  • Module
  • Class
  • Struct
  • Enum
  • Constructor
  • Method
  • Property
  • Field
  • Event
  • Interface
  • Parameter
  • Delegate
  • All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,
    ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )

~现在考虑下 AllowMultiple = false. 这就规定该 attribute 不能在同一语言元素上放置多次.

[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
    [Help("this is a do-nothing method")]        //error
    public void AnyMethod()
    {
    }
}

它产生了一个编译错误:

AnyClass.cs: Duplicate 'Help' attribute

Ok!现在我们该讨论下最后那个属性了,”Inherited”, 指出当把该attribute放置于一个基类之上,是否派生类也继承了该attribute。如果绑定至某个attribute类的”Inherited”被设为true,那么该attribute就会被继承,然而如果绑定至某个attribute类的”Inherited”被设为false或者没有定义,那么该attribute就不会被继承。

让我们假设有如下的类关系。

[Help("BaseClass")]
public class Base
{
}
 
public class Derive :  Base
{
}

我们有四种可能的绑定:

  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false )]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false) ]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true )]
  • [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true) ]

第一种情况

如果我们查询(我们将在后面来了解如何在运行时来查询attributes)派生类中的help attribute,我们将不可能查询到因为”Inherited”被设为了false。

第二种情况

第二种情况没有什么不同,因为其”Inherited”也被设为了false。

第三种情况

为了解释第三种和第四种情况,让我们为派生类也绑定同一attribute。

[Help("BaseClass")]
public class Base
{
}
 
[Help("DeriveClass")]
public class Derive :  Base
{
}

现在我们查询相关的help attribute ,我们将仅仅可以得到派生类的attribute,为什么这样是因为help attribute虽然允许被继承,但不能多次在同一语言元素上使用,所以基类中的help attribute被派生类的help attribute 重写了。

第四种情况

在第四种情况中,当我们查询派生类的help attribute 时,我们可以得到两个attributes,当然是因为help attribute既允许被继承,又允许在同一语言元素上多次使用的结果。

注意:AttributeUsage attribute 仅应用在那种是System.Attribute 派生的attriubte类而且绑定值该attriubte类的AllowMultiple和Inherited均为false上才是有效的。

相关文章