Menulis atribut kustom

Untuk merancang atribut kustom, Anda tidak perlu mempelajari banyak konsep baru. Jika Anda terbiasa dengan pemrograman berorientasi objek dan tahu cara merancang kelas, Anda sudah memiliki sebagian besar pengetahuan yang diperlukan. Atribut kustom adalah kelas tradisional yang berasal secara langsung atau tidak langsung dari System.Attribute kelas . Sama seperti kelas tradisional, atribut kustom berisi metode yang menyimpan dan mengambil data.

Langkah utama untuk merancang kelas atribut kustom dengan benar adalah sebagai berikut:

Bagian ini menjelaskan masing-masing langkah ini dan menyimpulkan dengan contoh atribut kustom.

Menerapkan AttributeUsageAttribute

Deklarasi atribut kustom dimulai dengan System.AttributeUsageAttribute atribut , yang menentukan beberapa karakteristik utama kelas atribut Anda. Misalnya, Anda dapat menentukan apakah atribut Anda dapat diwarisi oleh kelas lain atau elemen mana yang dapat diterapkan oleh atribut. Fragmen kode berikut menunjukkan cara menggunakan AttributeUsageAttribute:

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

AttributeUsageAttribute memiliki tiga anggota yang penting untuk pembuatan atribut kustom: AttributeTargets, Inherited, dan AllowMultiple.

Anggota AttributeTargets

Dalam contoh sebelumnya, AttributeTargets.All ditentukan, menunjukkan bahwa atribut ini dapat diterapkan ke semua elemen program. Atau, Anda dapat menentukan AttributeTargets.Class, menunjukkan bahwa atribut Anda hanya dapat diterapkan ke kelas, atau AttributeTargets.Method, yang menunjukkan bahwa atribut Anda hanya dapat diterapkan ke metode. Semua elemen program dapat ditandai untuk deskripsi dengan atribut kustom dengan cara ini.

Anda juga dapat meneruskan berbagai nilai AttributeTargets. Fragmen kode berikut menentukan bahwa atribut kustom dapat diterapkan ke kelas atau metode apa pun:

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

Detail Properti yang Diwariskan

Properti AttributeUsageAttribute.Inherited menunjukkan apakah atribut Anda dapat diwariskan oleh kelas yang berasal dari kelas tempat atribut Anda diterapkan. Properti ini mengambil true (default) atau bendera false. Dalam contoh berikut, MyAttribute memiliki nilai truedefault Inherited , sementara YourAttribute memiliki Inherited nilai false:

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

[AttributeUsage(AttributeTargets::Method, Inherited = false)]
public ref class YourAttribute : Attribute
{
    //...
};
// 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

Kedua atribut kemudian diterapkan ke metode di kelas MyClassdasar :

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

Akhirnya, kelas YourClass diwariskan dari kelas dasar MyClass. Metode MyMethod ini menunjukkan MyAttribute tetapi tidak YourAttribute:

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

};
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

Properti AllowMultiple

Properti AttributeUsageAttribute.AllowMultiple menunjukkan apakah beberapa instans atribut Anda dapat ada pada suatu elemen. Jika diatur ke true, beberapa instans diizinkan. Jika diatur ke false (default), hanya satu instans yang diizinkan.

Dalam contoh berikut, MyAttribute memiliki nilai falsedefault AllowMultiple , sementara YourAttribute memiliki nilai true:

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

[AttributeUsage(AttributeTargets::Method, AllowMultiple = true)]
public ref class YourAttribute : Attribute
{
};
//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

Saat beberapa instans atribut ini diterapkan, MyAttribute menghasilkan compiler error. Contoh kode berikut menunjukkan penggunaan YourAttribute yang valid dan penggunaan yang tidak valid dari MyAttribute:

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

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    void YourMethod()
    {
        //...
    }
};
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 Jika properti dan Inherited properti diatur ke true, kelas yang diwarisi dari kelas lain dapat mewarisi atribut dan memiliki instans lain dari atribut yang sama yang diterapkan di kelas turunan yang sama. Jika AllowMultiple diatur ke false, nilai atribut apa pun di kelas induk akan ditimpa oleh instans baru dari atribut yang sama di kelas turunan.

Mendeklarasikan kelas atribut

Setelah Anda menerapkan AttributeUsageAttribute, mulai tentukan spesifikasi atribut Anda. Deklarasi kelas atribut terlihat mirip dengan deklarasi kelas tradisional, seperti yang ditunjukkan oleh kode berikut:

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

Definisi atribut ini menunjukkan poin-poin berikut:

  • Kelas atribut harus dideklarasikan sebagai kelas publik.

  • Menurut konvensi, nama kelas atribut diakhir dengan kata Atribut. Meskipun tidak diperlukan, konvensi ini direkomendasikan untuk keterbacaan. Saat atribut diterapkan, penyertaan kata Atribut bersifat opsional.

  • Semua kelas atribut harus mewarisi secara langsung atau tidak langsung dari System.Attribute kelas .

  • Di Microsoft Visual Basic, semua kelas atribut kustom harus memiliki atribut System.AttributeUsageAttribute.

Mendeklarasikan konstruktor

Sama seperti kelas tradisional, atribut diinisialisasi dengan konstruktor. Fragmen kode berikut mengilustrasikan konstruktor atribut umum. Konstruktor publik ini mengambil parameter dan menetapkan variabel anggota yang sama dengan nilainya.

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

Anda dapat membebani konstruktor untuk mengakomodasi kombinasi nilai yang berbeda. Jika Anda juga menentukan properti untuk kelas atribut kustom, Anda dapat menggunakan kombinasi parameter bernama dan posisi saat menginisialisasi atribut. Biasanya, Anda menentukan semua parameter yang diperlukan sebagai parameter posisi dan semua parameter opsional seperti yang dinamai. Dalam hal ini, atribut tidak dapat diinisialisasi tanpa parameter yang diperlukan. Semua parameter bersifat opsional.

Catatan

Di Visual Basic, konstruktor untuk kelas atribut tidak boleh menggunakan ParamArray argumen.

Contoh kode berikut menunjukkan bagaimana atribut yang menggunakan konstruktor sebelumnya dapat diterapkan menggunakan parameter opsional dan diperlukan. Ini mengasumsikan bahwa atribut memiliki satu nilai Boolean yang diperlukan dan satu properti string opsional.

// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public ref class SomeClass
{
    //...
};
// One required (positional) parameter is applied.
[MyAttribute(false)]
public ref class SomeOtherClass
{
    //...
};
// 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

Mendeklarasikan properti

Jika Anda ingin menentukan parameter bernama atau menyediakan cara mudah untuk mengembalikan nilai yang disimpan oleh atribut Anda, nyatakan properti. Properti atribut harus dinyatakan sebagai entitas publik dengan deskripsi jenis data yang akan dikembalikan. Tentukan variabel yang akan menyimpan nilai properti Anda dan mengaitkannya dengan get metode dan set . Contoh kode berikut menunjukkan cara mengimplementasikan properti di atribut Anda:

property bool MyProperty
{
    bool get() {return this->myvalue;}
    void set(bool value) {this->myvalue = value;}
}
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

Contoh Atribut Kustom

Bagian ini menggabungkan informasi sebelumnya dan menunjukkan cara merancang atribut yang mendokumentasikan informasi tentang penulis bagian kode. Atribut dalam contoh ini menyimpan nama dan tingkat programmer, dan apakah kode telah ditinjau. Ini menggunakan tiga variabel privat untuk menyimpan nilai aktual untuk disimpan. Setiap variabel diwakili oleh properti publik yang mendapatkan dan mengatur nilai. Akhirnya, konstruktor didefinisikan dengan dua parameter yang diperlukan:

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

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

    DeveloperAttribute(String^ name, String^ level)
    {
        this->name = name;
        this->level = level;
        this->reviewed = false;
    }

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

    virtual property String^ Name
    {
        String^ get() {return name;}
    }

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

    virtual property String^ Level
    {
        String^ get() {return level;}
    }

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

    virtual property bool Reviewed
    {
        bool get() {return reviewed;}
        void set(bool value) {reviewed = 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;}
    }
}
<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

Anda dapat menerapkan atribut ini menggunakan nama lengkap, DeveloperAttribute, atau menggunakan nama singkatan, Developer, dengan salah satu cara berikut:

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

-or-

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

-or-

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

-or-

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

Contoh pertama menunjukkan atribut yang diterapkan hanya dengan parameter bernama yang diperlukan. Contoh kedua menunjukkan atribut yang diterapkan dengan parameter yang diperlukan dan opsional.

Lihat juga