共用方式為


寫入自訂屬性

若要設計自定義屬性,您不需要瞭解許多新概念。 如果您熟悉面向物件程序設計並知道如何設計類別,則您已經擁有所需的大部分知識。 自定義屬性是直接或間接衍生自 System.Attribute 類別的傳統類別。 如同傳統類別,自定義屬性包含儲存和擷取數據的方法。

正確設計自訂屬性類別的主要步驟如下:

本節說明上述每個步驟,並以 自定義屬性範例結尾。

套用 AttributeUsageAttribute

自定義屬性宣告的開頭是 System.AttributeUsageAttribute 屬性,它會定義屬性類別的一些關鍵特性。 例如,您可以指定屬性是否可以由其他類別繼承,或屬性可以套用至哪些元素。 下列代碼段示範如何使用 AttributeUsageAttribute

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
<AttributeUsage(AttributeTargets.All, Inherited:=False, AllowMultiple:=True)>
Public Class SomeClass
    Inherits Attribute
    '...
End Class

AttributeUsageAttribute有三個成員對於建立自定義屬性很重要:AttributeTargetsInheritedAllowMultiple

AttributeTargets 成員

在上述範例中, AttributeTargets.All 指定了 ,表示這個屬性可以套用至所有程序專案。 或者,您可以指定 AttributeTargets.Class,指出您的屬性只能套用至類別,或 AttributeTargets.Method,表示您的屬性只能套用至方法。 所有程式元素都可以以這種方式,透過自訂屬性來標記為描述。

您也可以傳遞多個 AttributeTargets 值。 下列代碼段指定自訂屬性可以套用至任何類別或方法:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method)>
Public Class SomeOtherClass
    Inherits Attribute
    '...
End Class

繼承的屬性

屬性 AttributeUsageAttribute.Inherited 指出您的屬性是否可以由衍生自套用屬性之類別的類別繼承。 這個屬性會採用 ( true 預設值) 或 false 旗標。 在下列範例中, MyAttribute 預設值Inherited為 ,而 trueYourAttributeInheritedfalse

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

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
    //...
}
' This defaults to Inherited = true.
Public Class MyAttribute
    Inherits Attribute
    '...
End Class

<AttributeUsage(AttributeTargets.Method, Inherited:=False)>
Public Class YourAttribute
    Inherits Attribute
    '...
End Class

然後,這兩個屬性會套用至基類 MyClass中的 方法:

public class MyClass
{
    [MyAttribute]
    [YourAttribute]
    public virtual void MyMethod()
    {
        //...
    }
}
Public Class MeClass
    <MyAttribute>
    <YourAttribute>
    Public Overridable Sub MyMethod()
        '...
    End Sub
End Class

最後,類別 YourClass 繼承自基類 MyClass。 方法MyMethod會顯示MyAttribute但不會顯示YourAttribute

public class YourClass : MyClass
{
    // MyMethod will have MyAttribute but not YourAttribute.
    public override void MyMethod()
    {
        //...
    }
}
Public Class YourClass
    Inherits MeClass
    ' MyMethod will have MyAttribute but not YourAttribute.
    Public Overrides Sub MyMethod()
        '...
    End Sub

End Class

AllowMultiple 屬性

屬性 AttributeUsageAttribute.AllowMultiple 會指出屬性的多個實例是否可以存在於 專案上。 如果設定為 true,則允許多個實例。 如果設定為 false (預設值),則只允許一個實例。

在下列範例中,MyAttribute預設值為 AllowMultiple ,而 false 的 值為 YourAttributetrue

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

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
' This defaults to AllowMultiple = false.
Public Class MyAttribute
    Inherits Attribute
End Class

<AttributeUsage(AttributeTargets.Method, AllowMultiple:=true)>
Public Class YourAttribute
    Inherits Attribute
End Class

套用這些屬性的多個實例時, 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()
    {
        //...
    }
}
Public Class MyClass
    ' This produces an error.
    ' Duplicates are not allowed.
    <MyAttribute>
    <MyAttribute>
    Public Sub MyMethod()
        '...
    End Sub

    ' This is valid.
    <YourAttribute>
    <YourAttribute>
    Public Sub YourMethod()
        '...
    End Sub
End Class

AllowMultiple如果 屬性和 Inherited 屬性都設定為 true,則繼承自另一個類別的類別可以繼承屬性,並在相同的子類別中套用相同屬性的另一個實例。 如果 AllowMultiple 設定為 false,父類別中任何屬性的值將會由子類別中相同屬性的新實例覆寫。

宣告屬性類別

套用 AttributeUsageAttribute 之後,開始定義屬性的具體細節。 屬性類別的宣告看起來類似於傳統類別的宣告,如下列程式代碼所示:

[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
    // . . .
}
<AttributeUsage(AttributeTargets.Method)>
Public Class MyAttribute
    Inherits Attribute
    ' . . .
End Class

此屬性定義示範下列幾點:

  • 屬性類別必須宣告為公用類別。

  • 依照慣例,屬性類別的名稱會以 Attribute 一字結尾。 雖然並非必要,但建議使用此慣例,以便閱讀。 套用屬性時,包含 Attribute 一詞是選擇性的。

  • 所有屬性類別都必須直接或間接繼承自 System.Attribute 類別。

  • 在 Microsoft Visual Basic 中,所有自定義屬性類別都必須具有 System.AttributeUsageAttribute 屬性。

宣告建構函式

就像傳統類別一樣,屬性會使用建構函式初始化。 下列代碼段說明一般屬性建構函式。 這個公用建構函式會採用 參數,並將成員變數設定為等於其值。

public MyAttribute(bool myvalue)
{
    this.myvalue = myvalue;
}
Public Sub New(myvalue As Boolean)
    Me.myvalue = myvalue
End Sub

您可以多載建構函式以容納不同的值組合。 如果您也為您的自定義屬性類別定義一個屬性,那麼在初始化該屬性時,您可以使用命名和位置參數的組合。 一般而言,您會將所有必要的參數定義為位置,並將所有選擇性參數定義為具名。 在此情況下,不需要必要的參數,就無法初始化 屬性。 所有其他參數皆為選擇性使用。

備註

在 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
{
    //...
}
' One required (positional) and one optional (named) parameter are applied.
<MyAttribute(false, OptionalParameter:="optional data")>
Public Class SomeClass
    '...
End Class

' One required (positional) parameter is applied.
<MyAttribute(false)>
Public Class SomeOtherClass
    '...
End Class

宣告屬性

如果您想要定義具名參數,或提供簡單的方法來傳回屬性所儲存的值,請宣告 屬性。 屬性屬性應該宣告為公用實體,其中包含將傳回之數據類型的描述。 定義變數,以保存屬性的值,並將它與 getset 方法產生關聯。 下列程式代碼範例示範如何在屬性中實現一個屬性。

public bool MyProperty
{
    get {return this.myvalue;}
    set {this.myvalue = value;}
}
Public Property MyProperty As Boolean
    Get
        Return Me.myvalue
    End Get
    Set
        Me.myvalue = Value
    End Set
End Property

自訂屬性範例

本節包含先前的資訊,並示範如何設計屬性,以記錄程式代碼區段作者的相關信息。 此範例中的 屬性會儲存程式設計人員的名稱和層級,以及程式代碼是否已檢閱。 它會使用三個私用變數來儲存實際的值。 每個變數都會以取得和設定值的公用屬性來表示。 最後,建構函式會使用兩個必要參數來定義:

[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;}
    }
}
<AttributeUsage(AttributeTargets.All)>
Public Class DeveloperAttribute
    Inherits Attribute
    ' Private fields.
    Private myname As String
    Private mylevel As String
    Private myreviewed As Boolean

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

    Public Sub New(name As String, level As String)
        Me.myname = name
        Me.mylevel = level
        Me.myreviewed = False
    End Sub

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

    Public Overridable ReadOnly Property Name() As String
        Get
            Return myname
        End Get
    End Property

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

    Public Overridable ReadOnly Property Level() As String
        Get
            Return mylevel
        End Get
    End Property

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

    Public Overridable Property Reviewed() As Boolean
        Get
            Return myreviewed
        End Get
        Set
            myreviewed = value
        End Set
    End Property
End Class

您可以透過下列其中一種方式,使用完整名稱、 DeveloperAttribute或使用縮寫名稱 Developer來套用此屬性:

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

-or-

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

-or-

<Developer("Joan Smith", "1", Reviewed := true)>

第一個範例顯示僅套用必要具名參數的屬性。 第二個範例顯示以必要和選擇性參數套用的屬性。

另請參閱