Psaní vlastních atributů

Pokud chcete navrhnout vlastní atributy, nemusíte se učit mnoho nových konceptů. Pokud znáte objektově orientované programování a víte, jak navrhovat třídy, už máte většinu potřebných znalostí. Vlastní atributy jsou tradiční třídy, které odvozují přímo nebo nepřímo z System.Attribute třídy. Stejně jako tradiční třídy vlastní atributy obsahují metody, které ukládají a načítají data.

Primární kroky pro správný návrh vlastních tříd atributů jsou následující:

Tato část popisuje každý z těchto kroků a končí příkladem vlastního atributu.

Použití atributuUsageAttribute

Deklarace vlastního atributu začíná atributem System.AttributeUsageAttribute , který definuje některé z klíčových charakteristik vaší třídy atributů. Můžete například určit, zda lze atribut zdědit jinými třídami nebo prvky, na které lze atribut použít. Následující fragment kódu ukazuje, jak použít 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 tři členy, které jsou důležité pro vytváření vlastních atributů: AttributeTargets, Inherited a AllowMultiple.

AttributeTargets – člen

V předchozím příkladu je zadán, což označuje, AttributeTargets.All že tento atribut lze použít pro všechny prvky programu. Alternativně můžete zadat AttributeTargets.Class, označující, že váš atribut lze použít pouze na třídu, nebo AttributeTargets.Method, označující, že atribut lze použít pouze pro metodu. Všechny prvky programu lze tímto způsobem označit k popisu vlastním atributem.

Můžete také předat více AttributeTargets hodnot. Následující fragment kódu určuje, že vlastní atribut lze použít pro libovolnou třídu nebo metodu:

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

Zděděná vlastnost

Vlastnost AttributeUsageAttribute.Inherited určuje, zda lze atribut dědit třídami odvozenými z tříd, na které je atribut použit. Tato vlastnost má příznak true (výchozí nastavení).false V následujícím příkladu MyAttribute má výchozí Inherited hodnotu true, zatímco YourAttributeInherited hodnotu 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

Dva atributy se pak použijí na metodu v základní třídě MyClass:

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

Nakonec je třída YourClass zděděna ze základní třídy MyClass. MyMethod Metoda ukazujeMyAttribute, ale neYourAttribute:

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

AllowMultiple – vlastnost

Vlastnost AttributeUsageAttribute.AllowMultiple označuje, zda může existovat více instancí atributu v elementu. Pokud je nastavená hodnota true, je povoleno více instancí. Pokud je nastavená hodnota false (výchozí), je povolena pouze jedna instance.

V následujícím příkladu MyAttribute má výchozí AllowMultiple hodnotu false, zatímco YourAttribute má hodnotu 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

Při použití více instancí těchto atributů dojde MyAttribute k chybě kompilátoru. Následující příklad kódu ukazuje platné použití a neplatné použití YourAttributeMyAttribute:

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 Pokud je vlastnost i Inherited vlastnost nastavena na true, třída zděděná z jiné třídy může dědit atribut a mít další instanci stejného atributu použitou ve stejné podřízené třídě. Pokud AllowMultiple je nastavena na falsehodnotu , hodnoty všech atributů v nadřazené třídě budou přepsány novými instancemi stejného atributu v podřízené třídě.

Deklarace třídy atributu

Po použití tohoto atributu AttributeUsageAttributezačněte definovat specifika atributu. Deklarace třídy atributu vypadá podobně jako deklarace tradiční třídy, jak ukazuje následující kód:

[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

Tato definice atributu ukazuje následující body:

  • Třídy atributů musí být deklarovány jako veřejné třídy.

  • Podle konvence končí název třídy atributu slovEm Attribute. I když to není povinné, doporučuje se tato konvence pro čitelnost. Při použití atributu je zahrnutí slova Atribut volitelné.

  • Všechny třídy atributů musí dědit přímo nebo nepřímo z System.Attribute třídy.

  • V jazyce Microsoft Visual Basic musí mít System.AttributeUsageAttribute všechny třídy vlastních atributů atribut.

Deklarování konstruktorů

Stejně jako tradiční třídy se atributy inicializují pomocí konstruktorů. Následující fragment kódu znázorňuje typický konstruktor atributů. Tento veřejný konstruktor přebírá parametr a nastaví členovou proměnnou, která se rovná její hodnotě.

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

Konstruktor můžete přetížit tak, aby vyhovoval různým kombinacím hodnot. Pokud také definujete vlastnost pro vlastní třídu atributů, můžete při inicializaci atributu použít kombinaci pojmenovaných a pozičních parametrů. Obvykle definujete všechny požadované parametry jako poziční a všechny volitelné parametry jako pojmenované. V tomto případě nelze atribut inicializovat bez požadovaného parametru. Všechny ostatní parametry jsou volitelné.

Poznámka:

V jazyce Visual Basic by konstruktory pro třídu atributu neměly používat ParamArray argument.

Následující příklad kódu ukazuje, jak lze použít atribut, který používá předchozí konstruktor pomocí volitelných a povinných parametrů. Předpokládá, že atribut má jednu požadovanou logickou hodnotu a jednu volitelnou řetězcovou vlastnost.

// 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

Deklarování vlastností

Pokud chcete definovat pojmenovaný parametr nebo poskytnout snadný způsob, jak vrátit hodnoty uložené atributem, deklarujte vlastnost. Vlastnosti atributu by měly být deklarovány jako veřejné entity s popisem datového typu, který bude vrácen. Definujte proměnnou, která bude obsahovat hodnotu vlastnosti, a přidružte ji k get metodám a set metodám. Následující příklad kódu ukazuje, jak implementovat vlastnost ve vašem atributu:

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

Příklad vlastního atributu

Tato část obsahuje předchozí informace a ukazuje, jak navrhnout atribut, který dokumentuje informace o autorovi oddílu kódu. Atribut v tomto příkladu ukládá název a úroveň programátora a zda byl kód zkontrolován. K uložení skutečných hodnot používá tři privátní proměnné. Každá proměnná je reprezentována veřejnou vlastností, která získá a nastaví hodnoty. Nakonec je konstruktor definován se dvěma požadovanými parametry:

[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

Tento atribut můžete použít pomocí úplného názvu DeveloperAttributenebo zkráceného názvu, Developera to jedním z následujících způsobů:

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

První příklad ukazuje atribut použitý pouze s požadovanými pojmenovanými parametry. Druhý příklad ukazuje atribut použitý s požadovanými i volitelnými parametry.

Viz také