Scrittura di attributi personalizzatiWriting Custom Attributes

Per progettare attributi personalizzati, non è necessario apprendere molti nuovi concetti.To design your own custom attributes, you do not need to master many new concepts. Se si ha familiarità con la programmazione orientata agli oggetti e si è in grado di progettare le classi, si ha già gran parte delle conoscenze necessarie.If you are familiar with object-oriented programming and know how to design classes, you already have most of the knowledge needed. Gli attributi personalizzati sono essenzialmente classi tradizionali che derivano direttamente o indirettamente da System.Attribute.Custom attributes are essentially traditional classes that derive directly or indirectly from System.Attribute. Analogamente alle classi tradizionali, gli attributi personalizzati contengono metodi che archiviano e recuperano dati.Just like traditional classes, custom attributes contain methods that store and retrieve data.

I passaggi fondamentali per progettare classi di attributi personalizzati sono i seguenti:The primary steps to properly design custom attribute classes are as follows:

Questa sezione illustra ognuno di questi passaggi e termina con esempio di attributo personalizzato.This section describes each of these steps and concludes with a custom attribute example.

Applicazione di AttributeUsageAttributeApplying the AttributeUsageAttribute

La dichiarazione di attributo personalizzato inizia con AttributeUsageAttribute, che definisce alcune delle caratteristiche chiave della classe di attributi.A custom attribute declaration begins with the AttributeUsageAttribute, which defines some of the key characteristics of your attribute class. Ad esempio, è possibile specificare se l'attributo può essere ereditato da altre classi o gli elementi a cui può essere applicato l'attributo.For example, you can specify whether your attribute can be inherited by other classes or specify which elements the attribute can be applied to. Il frammento di codice seguente illustra come specificare 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

L'oggetto System.AttributeUsageAttribute ha tre membri importanti per la creazione di attributi personalizzati: AttributeTargets, Inheritede AllowMultiple.The System.AttributeUsageAttribute has three members that are important for the creation of custom attributes: AttributeTargets, Inherited, and AllowMultiple.

Membro AttributeTargetsAttributeTargets Member

Nell'esempio precedente è specificato AttributeTargets , a indicare che questo attributo può essere applicato a tutti gli elementi di programma.In the previous example, AttributeTargets.All is specified, indicating that this attribute can be applied to all program elements. In alternativa, è possibile specificare AttributeTargets.Class, a indicare che l'attributo può essere applicato solo a una classe, oppure AttributeTargets.Method, a indicare che l'attributo può essere applicato solo a un metodo.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. Questa procedura può essere usata per contrassegnare tutti gli elementi di programma per la descrizione mediante un attributo personalizzato.All program elements can be marked for description by a custom attribute in this manner.

È anche possibile passare istanze multiple di AttributeTargets.You can also pass multiple instances of AttributeTargets. Il frammento di codice seguente specifica che un attributo personalizzato può essere applicato a qualsiasi classe o metodo.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

Proprietà InheritedInherited Property

La proprietà AttributeUsageAttribute.Inherited indica se l'attributo può essere ereditato da classi derivate dalle classi a cui è applicato l'attributo.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. Questa proprietà accetta un flag true (valore predefinito) o false .This property takes either a true (the default) or false flag. Nell'esempio seguente, ad esempio, MyAttribute ha una proprietà Inherited con il valore predefinito true, mentre YourAttribute ha una proprietà Inherited con valore false.For example, 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

I due attributi vengono quindi applicati a un metodo nella classe 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

Infine, la classe YourClass viene ereditata dalla classe base MyClass.Finally, the class YourClass is inherited from the base class MyClass. Il metodo MyMethod mostra MyAttribute, ma non 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

Proprietà AllowMultipleAllowMultiple Property

La proprietà AttributeUsageAttribute.AllowMultiple indica se in un elemento possono esistere istanze multiple dell'attributo.The AttributeUsageAttribute.AllowMultiple property indicates whether multiple instances of your attribute can exist on an element. Se è impostata su true, sono consentite istanze multiple. Se invece è impostata su false (valore predefinito), è consentita solo un'istanza.If set to true, multiple instances are allowed; if set to false (the default), only one instance is allowed.

Nell'esempio seguente MyAttribute ha una proprietà AllowMultiple con il valore predefinito false, mentre il valore di YourAttribute è 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

Quando vengono applicate istanze multiple di questi attributi, MyAttribute genera un errore del compilatore.When multiple instances of these attributes are applied, MyAttribute produces a compiler error. L'esempio di codice seguente mostra l'uso valido di YourAttribute e l'uso non valido di 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

Se le proprietà AllowMultiple e Inherited sono entrambe impostate su true, una classe ereditata da un'altra classe può ereditare un attributo e determinare l'applicazione di un'altra istanza dello stesso attributo nella stessa classe figlio.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. Se la proprietà AllowMultiple è impostata su false, i valori degli attributi nella classe padre verranno sovrascritti dalle nuove istanze dello stesso attributo nella classe figlio.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.

Dichiarazione della classe di attributiDeclaring the Attribute Class

Dopo avere applicato AttributeUsageAttribute, è possibile iniziare a definire le specifiche dell'attributo.After you apply the AttributeUsageAttribute, you can begin to define the specifics of your attribute. La dichiarazione di una classe di attributi è simile alla dichiarazione di una classe tradizionale, come dimostrato dal codice seguente.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

Questa definizione di attributo dimostra quanto segue:This attribute definition demonstrates the following points:

  • Le classi di attributi devono essere dichiarate come classi pubbliche.Attribute classes must be declared as public classes.

  • Per convenzione, il nome della classe di attributi termina con la parola Attribute.By convention, the name of the attribute class ends with the word Attribute. Sebbene non sia obbligatorio, questa convenzione è consigliabile per migliorare la leggibilità.While not required, this convention is recommended for readability. Quando l'attributo è applicato, l'inclusione della parola Attribute è facoltativa.When the attribute is applied, the inclusion of the word Attribute is optional.

  • Tutte le classi di attributi devono ereditare direttamente o indirettamente da System.Attribute.All attribute classes must inherit directly or indirectly from System.Attribute.

  • In Microsoft Visual Basic tutte le classi di attributi personalizzati devono avere l'attributo AttributeUsageAttribute .In Microsoft Visual Basic, all custom attribute classes must have the AttributeUsageAttribute attribute.

Dichiarazione dei costruttoriDeclaring Constructors

Gli attributi, così come le classi tradizionali, vengono inizializzati con costruttori.Attributes are initialized with constructors in the same way as traditional classes. Il frammento di codice seguente illustra un tipico costruttore di attributi.The following code fragment illustrates a typical attribute constructor. Questo costruttore pubblico accetta un parametro e ne imposta il valore uguale a una variabile membro.This public constructor takes a parameter and sets its value equal to a member variable.

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

È possibile eseguire l'overload del costruttore per supportare diverse combinazioni di valori.You can overload the constructor to accommodate different combinations of values. Se si definisce anche una proprietà per la classe di attributi personalizzati, è possibile usare una combinazione di parametri denominati e posizionali quando si inizializza l'attributo.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. In genere, tutti i parametri obbligatori vengono definiti come posizionali e tutti i parametri facoltativi come denominatiTypically, you define all required parameters as positional and all optional parameters as named. In questo caso, l'attributo non può essere inizializzato senza il parametro obbligatorio.In this case, the attribute cannot be initialized without the required parameter. Tutti gli altri parametri sono facoltativi.All other parameters are optional. Si noti che, in Visual Basic, i costruttori di una classe Attribute non devono usare un argomento ParamArray.Note that in Visual Basic, constructors for an attribute class should not use a ParamArray argument.

L'esempio di codice seguente illustra come applicare un attributo che usa il costruttore precedente mediante i parametri obbligatori e facoltativi.The following code example shows how an attribute that uses the previous constructor can be applied using optional and required parameters. Presuppone che l'attributo abbia un valore booleano obbligatorio e una proprietà stringa facoltativa.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

Dichiarazione delle proprietàDeclaring Properties

Se si vuole definire un parametro denominato o fornire un modo semplice per restituire i valori archiviati dall'attributo, dichiarare una proprietà.If you want to define a named parameter or provide an easy way to return the values stored by your attribute, declare a property. Le proprietà dell'attributo devono essere dichiarate come entità pubbliche con una descrizione del tipo di dati che verrà restituito.Attribute properties should be declared as public entities with a description of the data type that will be returned. Definire la variabile che conterrà il valore della proprietà e associarla ai metodi get e set .Define the variable that will hold the value of your property and associate it with the get and set methods. L'esempio di codice seguente illustra come implementare una semplice proprietà nell'attributo.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

esempio di attributo personalizzatoCustom Attribute Example

Questa sezione include le informazioni precedenti e illustra come progettare un semplice attributo che documenta le informazioni sull'autore di una sezione di codice.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'attributo in questo esempio archivia il nome e il livello del programmatore e specifica se il codice è stato rivisto.The attribute in this example stores the name and level of the programmer, and whether the code has been reviewed. Usa tre variabili private per archiviare i valori effettivi da salvare.It uses three private variables to store the actual values to save. Ogni variabile è rappresentata da una proprietà pubblica che ottiene e imposta i valori.Each variable is represented by a public property that gets and sets the values. Infine, il costruttore è definito con due parametri obbligatori.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

Questo attributo può essere applicato usando il nome completo DeveloperAttributeoppure il nome abbreviato Developerin uno dei modi seguenti.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)>

Il primo esempio mostra l'attributo applicato solo con i parametri denominati obbligatori, mentre il secondo esempio mostra l'attributo applicato con i parametri sia obbligatori che facoltativi.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.

Vedere ancheSee Also

System.Attribute
AttributeUsageAttribute
AttributiAttributes