使用英语阅读

通过


编写自定义属性

若要设计自定义属性,无需了解许多新概念。 如果你熟悉面向对象的编程并知道如何设计类,则你已拥有所需的大部分知识。 自定义属性是直接或间接派生自 System.Attribute 类的传统类。 与传统类一样,自定义属性包含存储和检索数据的方法。

正确设计自定义属性类的主要步骤如下:

本部分介绍上述每个步骤,最后以 自定义属性示例结束。

应用 AttributeUsageAttribute

自定义属性声明以属性开头 System.AttributeUsageAttribute ,该特性定义属性类的一些关键特征。 例如,可以指定属性是否可以由其他类继承,或者属性可以应用于哪些元素。 以下代码片段演示如何使用 AttributeUsageAttribute

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

AttributeUsageAttribute 三个成员对于创建自定义属性非常重要: AttributeTargetsInheritedAllowMultiple

AttributeTargets 成员

在前面的示例中, AttributeTargets.All 指定了此属性,指示此属性可应用于所有程序元素。 或者,可以指定 AttributeTargets.Class,指示属性只能应用于类,或者 AttributeTargets.Method指示属性只能应用于方法。 所有程序元素都可以以这种方式被自定义属性标记为说明。

还可以传递多个 AttributeTargets 值。 以下代码片段指定可将自定义属性应用于任何类或方法:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]

继承的属性

AttributeUsageAttribute.Inherited 属性指示属性是否可以由派生自应用属性的类继承。 此属性采用 true (默认值)或 false 标志。 在以下示例中,MyAttribute默认值Inheritedtrue为 ,而YourAttributeInherited默认值为false

// This defaults to Inherited = true.
public class MyAttribute : Attribute
{
    //...
}

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
    //...
}

然后,这两个属性将应用于基类 MyClass中的方法:

public class MyClass
{
    [MyAttribute]
    [YourAttribute]
    public virtual void MyMethod()
    {
        //...
    }
}

最后,类 YourClass 继承自基类 MyClass。 该方法MyMethod显示但不MyAttribute显示YourAttribute

public class YourClass : MyClass
{
    // MyMethod will have MyAttribute but not YourAttribute.
    public override void MyMethod()
    {
        //...
    }
}

AllowMultiple 属性

AttributeUsageAttribute.AllowMultiple 属性指示属性的多个实例是否可以存在于元素上。 如果设置为 true,则允许多个实例。 如果设置为 false (默认值),则只允许一个实例。

在以下示例中,MyAttribute默认值AllowMultiplefalse为 ,而YourAttribute默认值为true

//This defaults to AllowMultiple = false.
public class MyAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}

应用这些属性的多个实例时, MyAttribute 生成编译器错误。 下面的代码示例显示了有效用法 YourAttribute 和无效用法 MyAttribute

public class MyClass
{
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute]
    [MyAttribute]
    public void MyMethod()
    {
        //...
    }

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    public void YourMethod()
    {
        //...
    }
}

AllowMultiple如果属性和Inherited属性都设置为true,则从另一个类继承的类可以继承属性,并让同一子类中应用同一属性的另一个实例。 如果 设置为 />,则父类中任何属性的值将被子类中同一属性的新实例覆盖。

声明特性类

应用后 AttributeUsageAttribute,开始定义属性的具体信息。 特性类的声明类似于传统类的声明,如以下代码所示:

[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
    // . . .
}

此属性定义演示了以下几点:

  • 属性类必须声明为公共类。

  • 按照约定,属性类的名称以“ 属性”一词结尾。 虽然不需要,但建议使用此约定进行可读性。 应用该属性时,包含“属性”一词是可选的。

  • 所有属性类必须直接或间接地从 System.Attribute 类继承。

  • 在 Microsoft Visual Basic 中,所有自定义属性类都必须具有该 System.AttributeUsageAttribute 属性。

声明构造函数

与传统类一样,属性使用构造函数进行初始化。 以下代码片段演示了典型的属性构造函数。 此公共构造函数采用参数并设置一个等于其值的成员变量。

public MyAttribute(bool myvalue)
{
    this.myvalue = myvalue;
}

可以重载构造函数以适应值的不同组合。 如果还为自定义属性类定义 属性 ,则可以在初始化属性时使用命名参数和位置参数的组合。 通常,将所有必需的参数定义为位置参数和命名的所有可选参数。 在这种情况下,如果没有必需的参数,则无法初始化特性。 所有其他参数都是可选的。

备注

在 Visual Basic 中,属性类的构造函数不应使用 ParamArray 参数。

下面的代码示例演示如何使用可选参数和必需参数应用使用上一个构造函数的属性。 它假定该属性具有一个必需的布尔值和一个可选的字符串属性。

// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public class SomeClass
{
    //...
}
// One required (positional) parameter is applied.
[MyAttribute(false)]
public class SomeOtherClass
{
    //...
}

声明属性

如果要定义命名参数或提供返回属性存储的值的简单方法,请声明 属性。 属性属性应声明为公共实体,其中包含将返回的数据类型的说明。 定义将保存属性值的变量,并将其与 getset 方法相关联。 下面的代码示例演示如何在属性中实现属性:

public bool MyProperty
{
    get {return this.myvalue;}
    set {this.myvalue = value;}
}

自定义属性示例

本部分包含前面的信息,并演示如何设计一个属性,该属性记录有关代码节的作者的信息。 此示例中的属性存储程序员的名称和级别,以及代码是否已评审。 它使用三个私有变量来存储要保存的实际值。 每个变量由获取和设置值的公共属性表示。 最后,使用两个必需参数定义构造函数:

[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : Attribute
{
    // Private fields.
    private string name;
    private string level;
    private bool reviewed;

    // This constructor defines two required parameters: name and level.

    public DeveloperAttribute(string name, string level)
    {
        this.name = name;
        this.level = level;
        this.reviewed = false;
    }

    // Define Name property.
    // This is a read-only attribute.

    public virtual string Name
    {
        get {return name;}
    }

    // Define Level property.
    // This is a read-only attribute.

    public virtual string Level
    {
        get {return level;}
    }

    // Define Reviewed property.
    // This is a read/write attribute.

    public virtual bool Reviewed
    {
        get {return reviewed;}
        set {reviewed = value;}
    }
}

可以通过以下方法之一使用全名 DeveloperAttribute或缩写名称 Developer来应用此属性:

[Developer("Joan Smith", "1")]

-or-

[Developer("Joan Smith", "1", Reviewed = true)]

第一个示例演示仅应用了必需的命名参数的属性。 第二个示例显示了使用必需参数和可选参数应用的属性。

另请参阅


其他资源

文档