C# 特性(Attribute)入门(二)

定义或控制特性的使用

AttributeUsage 类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。

AttributeUsage 有三个属性,我们可以把它放置在定制属性前面。第一个属性是:

** ValidOn **

通过这个属性,我们能够定义定制特性应该在何种程序实体前放置。一个属性可以被放置的所有程序实体在 AttributeTargets enumerator 中列出。通过 OR 操作我们可以把若干个 AttributeTargets 值组合起来。

** AllowMultiple **

这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次。

** Inherited **

我们可以使用这个属性来控制定制特性的继承规则。它标记了我们的特性能否被继承。

下面让我们来做一些实际的东西。我们将会在刚才的 Help 特性前放置 AttributeUsage 特性以期待在它的帮助下控制 Help 特性的使用。

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 特性只能被放在 class 的前面。这也就意味着下面的代码将会产生错误:

[Help("this is a do-nothing class")]


public class AnyClass


{


    [Help("this is a do-nothing method")]    _//error_


    public void AnyMethod()


    {


    }


} 

编译器报告错误如下:

AnyClass.cs: Attribute 'Help' is not valid on this declaration type.

It is valid on 'class' declarations only.

我们可以使用 AttributeTargets.All 来允许 Help 特性被放置在任何程序实体前。可能的值是:

  • 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 。它规定了特性不能被重复放置多次。

[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, 表明当特性被放置在一个基类上时,它能否被派生类所继承。

[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 ]

** 第一种情况: ** ** **

如果我们查询( Query )(稍后我们会看到如何在运行期查询一个类的特性) Derive 类,我们将会发现 Help 特性并不存在,因为 inherited 属性被设置为 false 。

** 第二种情况: ** ** **

和第一种情况相同,因为 inherited 也被设置为 false 。


** 第三种情况: ** ** **

为了解释第三种和第四种情况,我们先来给派生类添加点代码:

[Help("BaseClass")] 


public class Base


{


}


[Help("DeriveClass")] 


public class Derive :  Base


{


}

现在我们来查询一下 Help 特性,我们只能得到派生类的属性,因为 inherited 被设置为 true ,但是 AllowMultiple 却被设置为 false 。因此基类的 Help 特性被派生类 Help 特性覆盖了。

** 第四种情况: ** ** **

在这里,我们将会发现派生类既有基类的 Help 特性,也有自己的 Help 特性,因为 AllowMultiple 被设置为 true 。

Published At
Categories with Web编程
Tagged with
comments powered by Disqus