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
Má 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 YourAttribute
má Inherited 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í YourAttribute
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 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 false
hodnotu , 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 DeveloperAttribute
nebo zkráceného názvu, Developer
a 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.