Écriture des attributs personnalisés
Mise à jour : novembre 2007
Pour concevoir vos propres attributs personnalisés, vous n'avez pas besoin de maîtriser beaucoup de nouveaux concepts. Si vous avez l'habitude de la programmation orientée objet et savez concevoir des classes, vous avez déjà la majorité des connaissances nécessaires. Les attributs personnalisés sont essentiellement des classes traditionnelles qui dérivent directement ou indirectement de System.Attribute. Tout comme les classes traditionnelles, les attributs personnalisés contiennent des méthodes qui enregistrent et récupèrent les données.
Les premières étapes permettant de concevoir correctement des classes d'attributs personnalisées sont les suivantes :
Application de AttributeUsageAttribute
Déclaration de la classe d'attributs
Déclaration des constructeurs
Déclaration des propriétés
Cette section décrit chacune de ces étapes et conclut par un exemple d'attribut personnalisé.
Application de AttributeUsageAttribute
Une déclaration attribute personnalisée commence par le AttributeUsageAttribute, qui définit certaines des caractéristiques clés de votre classe d'attributs. Par exemple, vous pouvez spécifier si d'autres classes peuvent hériter de votre attribut ou indiquer les éléments auxquels l'attribut peut être appliqué. Le fragment de code suivant illustre comment utiliser le AttributeUsageAttribute.
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
<AttributeUsage(AttributeTargets.All, Inherited := False, AllowMultiple := true)>
System.AttributeUsageAttribute a trois membres qui sont importants pour la création des attributs personnalisés : AttributeTargets, Inherited et AllowMultiple.
AttributeTargets, membre
Dans l'exemple précédent, AttributeTargets.Allest spécifié, indiquant que cet attribut peut être appliqué à tous les éléments du programme. Vous pouvez également spécifier AttributeTargets.Class, indiquant que votre attribut ne peut être appliqué qu'à une classe ou AttributeTargets.Method, indiquant que votre attribut ne peut être appliqué qu'à une méthode. Tous les éléments du programme peuvent être, de cette manière, marqués pour description par un attribut personnalisé.
Vous pouvez également passer plusieurs instances de AttributeTargets. Le fragment de code suivant spécifie qu'un attribut personnalisé peut être appliqué à n'importe quelle classe ou méthode.
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method)]
<AttributeUsage (AttributeTargets.Class Or AttributeTargets.Method)>
Inherited, propriété
La propriété Inherited indique si les classes dérivées de celles auxquelles votre attribut s'applique peuvent hériter de votre attribut. Cette propriété accepte un indicateur true (valeur par défaut) ou false. Dans l'exemple de code suivant, MyAttribute a une valeur Inheritedtrue par défaut, tandis que YourAttribute a une valeur Inheritedfalse.
//This defaults to Inherited = true.
public class MyAttribute :Attribute
{
}
[AttributeUsage( Inherited = false)]
public class YourAttribute : Attribute
{
}
<AttributeUsage( AttributeTargets.All, Inherited := True)> Public Class _
MyAttribute
Inherits Attribute
End Class
<AttributeUsage( AttributeTargets.All, Inherited := False)> Public Class _
YourAttribute
Inherits Attribute
End Class
Les deux attributs sont alors appliqués à une méthode dans la classe de base MyClass.
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
//...
}
}
' In Microsoft Visual Basic, you apply multiple attributes
' by separating them with commas.
Public Class [MyClass]
<MyAttribute, YourAttribute> Public Overridable Sub MyMethod()
'...
End Sub
End Class
Finalement, la classe YourClass est héritée de la classe de base MyClass. La méthode MyMethod indique MyAttribute, mais pas YourAttribute.
public class YourClass: MyClass
{
//MyMethod will have MyAttribute but not YourAttribute.
public override void MyMethod()
{
//...
}
}
Public Class YourClass
Inherits [MyClass]
'MyMethod will have MyAttribute but not YourAttribute.
Public overrides Sub MyMethod()
'...
End Sub
End Class
AllowMultiple, propriété
La propriété AllowMultiple indique si plusieurs instances de votre attribut peuvent exister sur un élément. Si elle a la valeur true, plusieurs instances sont autorisées ; si elle a la valeur false (par défaut), une seule instance est autorisée.
Dans l'exemple de code suivant, MyAttribute a la valeur AllowMultiplefalse par défaut, tandis que YourAttribute a la valeur true.
//This defaults to AllowMultiple = false.
public class MyAttribute :Attribute
{
}
[AttributeUsage(AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
'This defaults to AllowMultiple = false.
<AttributeUsage(AttributeTargets.Method)> Public Class _
MyAttribute
Inherits Attribute
End Class
<AttributeUsage(AttributeTargets.Method, AllowMultiple := True)> Public Class _
YourAttribute
Inherits Attribute
End Class
Lorsque plusieurs instances de ces attributs sont appliquées, MyAttribute génère une erreur de compilateur. L'exemple de code suivant indique l'utilisation valide de YourAttribute et l'utilisation non valide de 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(){
//...
}
}
' In Microsoft Visual Basic you apply multiple attributes
' by separating them with commas.
Public Class [MyClass]
'This produces an error.
'Duplicates are not allowed.
<MyAttribute, MyAttribute> Public Overridable Sub MyMethod()
'...
End Sub
'This is valid.
<YourAttribute, YourAttribute> Public Sub YourMethod()
'...
End Sub
End Class
Si true est affecté aux deux propriétés AllowMultiple et Inherited, une classe héritée d'une autre peut hériter d'un attribut et avoir une autre instance du même attribut appliquée dans la même classe enfant. Si false est affecté à AllowMultiple, les valeurs des attributs de la classe parente seront écrasées par toute nouvelle instance du même attribut de la classe enfant.
Déclaration de la classe d'attributs
Après avoir appliqué AttributeUsageAttribute, vous pouvez commencer à définir les particularités de votre attribut. La déclaration d'une classe d'attributs ressemble à la déclaration d'une classe traditionnelle, comme cela est démontré par le code suivant.
public class MyAttribute : System.Attribute
{
// . . .
}
' This attribute is only usable with methods
<AttributeUsage(AttributeTargets.Method)> Public Class MyAttribute
Inherits System.Attribute
' . . .
End Class
Cette définition de l'attribut illustre les points suivants :
Les classes d'attributs doivent être déclarées comme des classes publiques.
Par convention, le nom de la classe d'attributs se termine par le mot Attribute. Bien qu'il ne soit pas obligatoire, le respect de cette convention est recommandé pour la lisibilité. Lorsque l'attribut est appliqué, l'inclusion du mot Attribute est optionnelle.
Toutes les classes d'attributs doivent hériter directement ou indirectement de System.Attribute.
Dans Microsoft Visual Basic, toutes les classes d'attributs personnalisés doivent avoir l'attribut AttributeUsageAttribute.
Déclaration des constructeurs
Les attributs sont initialisés avec les constructeurs de la même façon que les classes traditionnelles. Le fragment de code suivant illustre un constructeur d'attribut classique. Ce constructeur public accepte un paramètre et lui affecte une valeur égale à la variable membre.
public MyAttribute(bool myvalue)
{
this.myvalue = myvalue;
}
Public Sub New(newvalue As Boolean)
Me.myvalue = newvalue
End Sub
Vous pouvez surcharger le constructeur afin d'accueillir les différentes combinaisons des valeurs. Si vous définissez également une propriété pour votre classe d'attributs personnalisés, vous pouvez utiliser une combinaison de paramètres nommés et positionnels lors de l'initialisation de l'attribut. Vous définissez généralement tous les paramètres obligatoires comme positionnels et tous les paramètres optionnels comme nommés. Dans ce cas, l'attribut ne peut pas être initialisé sans le paramètre obligatoire. Tous les autres paramètres sont optionnels. Notez qu'en Visual Basic, les constructeurs d'une classe d'attributs ne doivent pas utiliser d'argument ParamArray.
L'exemple de code suivant montre comment un attribut utilisant le constructeur précédent peut être appliqué à l'aide des paramètres obligatoires et optionnels. Il suppose que l'attribut a une valeur booléenne obligatoire et une propriété de type chaîne optionnelle.
//One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
//One required (positional) parameter is applied.
[MyAttribute(false)]
'One required (positional) and one optional (named) parameter are applied.
<MyAttribute(False, OptionalParameter := "optional data")>
' ...
'One required (positional) parameter is applied.
<MyAttribute(False)>
Déclaration des propriétés
Si vous souhaitez définir un paramètre nommé ou permettre le retour aisé des valeurs enregistrées par votre attribut, déclarez une propriété. Les propriétés d'attribut doivent être déclarées comme des entités publiques avec une description du type de données qui sera retourné. Définissez la variable qui contiendra la valeur de votre propriété et associez-la aux méthodes get et set. L'exemple de code suivant illustre comment implémenter une propriété simple dans votre attribut.
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
Exemple d'attribut personnalisé
Cette section regroupe les informations précédentes et montre comment concevoir un attribut simple qui documente les informations concernant l'auteur d'une section de code. Dans cet exemple, l'attribut enregistre le nom et le niveau du programmateur et indique si le code a été révisé. Il utilise trois variables privées pour enregistrer les valeurs réelles à sauvegarder. Chaque variable est représentée par une propriété publique qui obtient et définit les valeurs. Finalement, le constructeur est défini avec deux paramètres obligatoires.
[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : System.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 System.Attribute
'Private fields.
Private m_name As String
Private m_level As String
Private m_reviewed As Boolean
'This constructor defines two required parameters: name and level.
Public Sub New(name As String, level As String)
Me.m_name = name
Me.m_level = level
Me.m_reviewed = False
End Sub
'Define Name property.
'This is a read-only attribute.
Public Overridable ReadOnly Property Name() As String
Get
Return m_name
End Get
End Property
'Define Level property.
'This is a read-only attribute.
Public Overridable ReadOnly Property Level() As String
Get
Return m_level
End Get
End Property
'Define Reviewed property.
'This is a read/write attribute.
Public Overridable Property Reviewed() As Boolean
Get
Return m_reviewed
End Get
Set
m_reviewed = value
End Set
End Property
End Class
Vous pouvez appliquer cet attribut à l'aide du nom complet, DeveloperAttribute, ou du nom abrégé, Developer, de l'une des manières suivantes.
[Developer("Joan Smith", "1")]
[Developer("Joan Smith", "1", Reviewed = true)]
<Developer("Joan Smith", "1")>
<Developer("Joan Smith", "1", Reviewed := True)>
Le premier exemple montre l'application de l'attribut avec seulement les paramètres nommés obligatoires, tandis que le deuxième exemple montre l'application de l'attribut avec les paramètres obligatoires et optionnels.