Écriture des attributs personnalisésWriting Custom Attributes

Pour concevoir vos propres attributs personnalisés, vous n’avez pas besoin de maîtriser les nombreux nouveaux concepts.To design your own custom attributes, you do not need to master many new concepts. Si vous êtes familiarisé avec la programmation orientée objet et savez concevoir des classes, vous possédez déjà la plupart des connaissances nécessaires.If you are familiar with object-oriented programming and know how to design classes, you already have most of the knowledge needed. Les attributs personnalisés sont essentiellement des classes traditionnelles qui dérivent directement ou indirectement de System.Attribute.Custom attributes are essentially traditional classes that derive directly or indirectly from System.Attribute. Tout comme les classes traditionnelles, les attributs personnalisés contiennent des méthodes qui stockent et récupèrent les données.Just like traditional classes, custom attributes contain methods that store and retrieve data.

Les principales étapes permettant de concevoir correctement des classes d’attributs personnalisés sont les suivantes :The primary steps to properly design custom attribute classes are as follows:

Cette section décrit chacune de ces étapes et se termine par un exemple d’attribut personnalisé.This section describes each of these steps and concludes with a custom attribute example.

Application d’AttributeUsageAttributeApplying the AttributeUsageAttribute

Une déclaration d’attribut personnalisé commence par System.AttributeUsageAttribute, qui définit certaines caractéristiques clés de votre classe d’attributs.A custom attribute declaration begins with the System.AttributeUsageAttribute, which defines some of the key characteristics of your attribute class. Par exemple, vous pouvez spécifier si votre attribut peut être hérité par d’autres classes ou spécifier les éléments auxquels l’attribut peut être appliqué.For example, you can specify whether your attribute can be inherited by other classes or specify which elements the attribute can be applied to. Le fragment de code suivant montre comment utiliser l’attribut AttributeUsageAttribute.The following code fragment demonstrates how to use the 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 possède trois membres importants pour la création d’attributs personnalisés : AttributeTargets, Inheritedet AllowMultiple.The AttributeUsageAttribute has three members that are important for the creation of custom attributes: AttributeTargets, Inherited, and AllowMultiple.

Membre AttributeTargetsAttributeTargets Member

Dans l’exemple précédent, AttributeTargets.All est spécifié, ce qui indique que cet attribut peut être appliqué à tous les éléments de programme.In the previous example, AttributeTargets.All is specified, indicating that this attribute can be applied to all program elements. Vous pouvez également spécifier AttributeTargets.Class, qui indique que votre attribut peut être appliqué uniquement à une classe, ou AttributeTargets.Method, qui indique que votre attribut peut être appliqué uniquement à une méthode.Alternatively, you can specify AttributeTargets.Class, indicating that your attribute can be applied only to a class, or AttributeTargets.Method, indicating that your attribute can be applied only to a method. Tous les éléments de programme peuvent être marqués pour description par un attribut personnalisé de cette manière.All program elements can be marked for description by a custom attribute in this manner.

Vous pouvez également transmettre plusieurs valeurs de AttributeTargets.You can also pass multiple AttributeTargets values. Le fragment de code suivant spécifie qu’un attribut personnalisé peut être appliqué à n’importe quelle classe ou méthode.The following code fragment specifies that a custom attribute can be applied to any class or method.

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

Propriété InheritedInherited Property

La propriété AttributeUsageAttribute.Inherited indique si votre attribut peut être hérité par les classes qui sont dérivées des classes auxquelles votre attribut est appliqué.The AttributeUsageAttribute.Inherited property indicates whether your attribute can be inherited by classes that are derived from the classes to which your attribute is applied. Cette propriété reçoit un indicateur true (par défaut) ou false.This property takes either a true (the default) or false flag. Dans l’exemple suivant, MyAttribute affiche une valeur par défaut Inherited de true, tandis YourAttribute affiche une valeur Inherited de false.In the following example, MyAttribute has a default Inherited value of true, while YourAttribute has an Inherited value of 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

Les deux attributs sont ensuite appliqués à une méthode dans la classe de base MyClass.The two attributes are then applied to a method in the base class 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

Enfin, la classe YourClass est héritée de la classe de base MyClass.Finally, the class YourClass is inherited from the base class MyClass. La méthode MyMethod affiche MyAttribute, mais pas YourAttribute.The method MyMethod shows MyAttribute, but not 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

Propriété AllowMultipleAllowMultiple Property

La propriété AttributeUsageAttribute.AllowMultiple indique si plusieurs instances de votre attribut peuvent exister sur un élément.The AttributeUsageAttribute.AllowMultiple property indicates whether multiple instances of your attribute can exist on an element. Si la valeur est true, plusieurs instances sont autorisées, si la valeur est false (par défaut), une seule instance est autorisée.If set to true, multiple instances are allowed; if set to false (the default), only one instance is allowed.

Dans l’exemple suivant, MyAttribute affiche une valeur par défaut AllowMultiple de false, tandis YourAttribute affiche une valeur de true.In the following example, MyAttribute has a default AllowMultiple value of false, while YourAttribute has a value of 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

Quand plusieurs instances de ces attributs sont appliquées, MyAttribute génère une erreur du compilateur.When multiple instances of these attributes are applied, MyAttribute produces a compiler error. L’exemple de code suivant illustre l’utilisation valide de YourAttribute et l’utilisation non valide de MyAttribute.The following code example shows the valid use of YourAttribute and the invalid use of 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

Si la propriété AllowMultiple et la propriété Inherited ont la valeur true, une classe héritée d’une autre classe peut hériter d’un attribut et avoir une autre instance du même attribut appliquée dans la même classe enfant.If both the AllowMultiple property and the Inherited property are set to true, a class that is inherited from another class can inherit an attribute and have another instance of the same attribute applied in the same child class. Si AllowMultiple a la valeur false, les valeurs des attributs de la classe parente sont remplacées par les nouvelles instances du même attribut dans la classe enfant.If AllowMultiple is set to false, the values of any attributes in the parent class will be overwritten by new instances of the same attribute in the child class.

Déclaration de la classe d’attributsDeclaring the Attribute Class

Une fois que vous avez appliqué AttributeUsageAttribute, vous pouvez commencer à définir les particularités de votre attribut.After you apply the AttributeUsageAttribute, you can begin to define the specifics of your attribute. La déclaration d’une classe d’attributs ressemble à la déclaration d’une classe traditionnelle, comme illustré dans le code suivant.The declaration of an attribute class looks similar to the declaration of a traditional class, as demonstrated by the following code.

[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

Cette définition de l’attribut illustre les points suivants :This attribute definition demonstrates the following points:

  • Les classes d’attributs doivent être déclarées comme des classes publiques.Attribute classes must be declared as public classes.

  • Par convention, le nom de la classe d’attributs se termine par le mot Attribute.By convention, the name of the attribute class ends with the word Attribute. Même si elle n’est pas obligatoire, cette convention est recommandée pour une meilleure lisibilité.While not required, this convention is recommended for readability. Quand l’attribut est appliqué, l’inclusion du mot Attribute est facultative.When the attribute is applied, the inclusion of the word Attribute is optional.

  • Toutes les classes d’attributs doivent hériter directement ou indirectement de System.Attribute.All attribute classes must inherit directly or indirectly from System.Attribute.

  • Dans Microsoft Visual Basic, toutes les classes d’attributs personnalisés doivent avoir l’attribut System.AttributeUsageAttribute.In Microsoft Visual Basic, all custom attribute classes must have the System.AttributeUsageAttribute attribute.

Déclaration des constructeursDeclaring Constructors

Les attributs sont initialisés avec des constructeurs de la même façon que les classes traditionnelles.Attributes are initialized with constructors in the same way as traditional classes. Le fragment de code suivant illustre un constructeur d’attribut classique.The following code fragment illustrates a typical attribute constructor. Ce constructeur public accepte un paramètre et définit une variable membre égale à sa valeur.This public constructor takes a parameter and sets a member variable equal to its value.

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

Vous pouvez surcharger le constructeur pour qu’il reçoive différentes combinaisons de valeurs.You can overload the constructor to accommodate different combinations of values. 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.If you also define a property for your custom attribute class, you can use a combination of named and positional parameters when initializing the attribute. En général, vous définissez tous les paramètres obligatoires comme des paramètres positionnels et tous les paramètres facultatifs comme des paramètres nommés.Typically, you define all required parameters as positional and all optional parameters as named. Dans ce cas, l’attribut ne peut pas être initialisé sans le paramètre obligatoire.In this case, the attribute cannot be initialized without the required parameter. Tous les autres paramètres sont facultatifs.All other parameters are optional. Notez que dans Visual Basic, les constructeurs d’une classe d’attributs ne doivent pas utiliser d’argument ParamArray.Note that in Visual Basic, constructors for an attribute class should not use a ParamArray argument.

L’exemple de code suivant montre comment un attribut qui utilise le constructeur précédent peut être appliqué à l’aide de paramètres obligatoires et facultatifs.The following code example shows how an attribute that uses the previous constructor can be applied using optional and required parameters. Il suppose que l’attribut a une valeur booléenne obligatoire et une propriété de chaîne facultative.It assumes that the attribute has one required Boolean value and one optional string property.

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

Déclaration des propriétésDeclaring Properties

Si vous voulez définir un paramètre nommé ou fournir un moyen facile de retourner les valeurs stockées par votre attribut, déclarez une propriété.If you want to define a named parameter or provide an easy way to return the values stored by your attribute, declare a property. Les propriétés d’attribut doivent être déclarées comme des entités publiques avec une description du type de données à retourner.Attribute properties should be declared as public entities with a description of the data type that will be returned. Définissez la variable qui contient la valeur de votre propriété et associez-la aux méthodes get et set.Define the variable that will hold the value of your property and associate it with the get and set methods. L’exemple de code suivant montre comment implémenter une propriété simple dans votre attribut.The following code example demonstrates how to implement a simple property in your attribute.

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

exemple d’attribut personnaliséCustom Attribute Example

Cette section intègre les informations précédentes et montre comment concevoir un attribut simple qui documente des informations sur l’auteur d’une section de code.This section incorporates the previous information and shows how to design a simple attribute that documents information about the author of a section of code. L’attribut de cet exemple stocke le nom et le niveau du programmeur, et indique si le code a été révisé.The attribute in this example stores the name and level of the programmer, and whether the code has been reviewed. Il utilise trois variables privées pour stocker les valeurs réelles à enregistrer.It uses three private variables to store the actual values to save. Chaque variable est représentée par une propriété publique qui obtient et définit les valeurs.Each variable is represented by a public property that gets and sets the values. Enfin, le constructeur est défini avec deux paramètres obligatoires.Finally, the constructor is defined with two required parameters.

[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

Vous pouvez appliquer cet attribut à l’aide du nom complet, DeveloperAttribute, ou à l’aide du nom abrégé, Developer, de l’une des manières suivantes.You can apply this attribute using the full name, DeveloperAttribute, or using the abbreviated name, Developer, in one of the following ways.

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

Le premier exemple montre l’attribut appliqué uniquement avec les paramètres nommés obligatoires, tandis que le deuxième exemple montre l’attribut appliqué avec les paramètres obligatoires et facultatifs.The first example shows the attribute applied with only the required named parameters, while the second example shows the attribute applied with both the required and optional parameters.

Voir aussiSee also