Attributi
Gli attributi offrono un metodo efficace per l'associazione di metadati o informazioni dichiarative con il codice (assembly, tipi, metodi, proprietà e così via). Dopo aver associato un attributo a un'entità di programma, in fase di esecuzione è possibile eseguire una query su tale attributo usando una tecnica denominata reflection.
Di seguito sono riportate le proprietà degli attributi:
- Gli attributi aggiungono metadati al programma. I metadati sono informazioni relative ai tipi definiti in un programma. Tutti gli assembly .NET contengono un set specificato di metadati che descrive i tipi e membri dei tipi definiti nell'assembly. È possibile aggiungere attributi personalizzati per specificare altre informazioni eventualmente necessarie.
- È possibile applicare uno o più attributi a interi assembly, moduli o elementi di programma di minori dimensioni, ad esempio classi e proprietà.
- Gli attributi possono accettare argomenti nello stesso modo dei metodi e delle proprietà.
- Il programma può esaminare i propri metadati oppure i metadati di un altro programma tramite reflection.
La reflection specifica oggetti di tipo Type che descrivono assembly, moduli e tipi. È possibile usare la reflection per creare in modo dinamico un'istanza di un tipo, associare il tipo a un oggetto esistente oppure ottenere il tipo da un oggetto esistente e richiamarne i metodi o accedere ai relativi campi e proprietà. Se usi attributi nel codice, la reflection consente di accedervi. Per altre informazioni, vedere Attributi.
Di seguito è riportato un esempio semplice di reflection che usa il metodo GetType() ereditato da tutti i tipi dalla classe di base Object
per ottenere il tipo di una variabile:
Nota
Assicurati di aggiungere using System;
e using System.Reflection;
nella parte superiore del file .cs.
// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
L'output è: System.Int32
.
L'esempio seguente usa la reflection per ottenere il nome completo dell'assembly caricato.
// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);
L'output è simile al seguente: System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
.
Nota
Le parole chiave di C# protected
e internal
non hanno significato nel linguaggio intermedio (IL) e non sono usate nelle API di reflection. I termini corrispondenti in IL sono Famiglia e Assembly. Per identificare un metodo internal
tramite reflection, usare la proprietà IsAssembly. Per identificare un metodo protected internal
, usare IsFamilyOrAssembly.
Usare gli attributi
È possibile usare attributi in quasi tutte le dichiarazioni, anche se la validità di un attributo specifico può essere limitata ad alcuni tipi di dichiarazione. Per specificare un attributo in C# inserisci il nome dell'attributo racchiuso tra parentesi quadre ([]
) sopra la dichiarazione dell'entità a cui è applicato.
Nell'esempio seguente l'attributo SerializableAttribute viene usato per applicare una caratteristica specifica a una classe:
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
Un metodo con l'attributo DllImportAttribute è dichiarato come nell'esempio seguente:
[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();
In una dichiarazione è possibile inserire più attributi, come illustrato nell'esempio seguente:
void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }
Alcuni attributi possono essere specificati più volte per una stessa entità. Un esempio di attributo multiuso è ConditionalAttribute:
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
Nota
Per convenzione tutti i nomi di attributo terminano con la parola "Attribute", in modo che sia possibile distinguerli da altri elementi delle librerie .NET. Tuttavia, quando gli attributi vengono usati nel codice, non è necessario specificare il suffisso Attribute. Ad esempio [DllImport]
è equivalente a [DllImportAttribute]
, mentre DllImportAttribute
è il nome effettivo dell'attributo nella libreria di classi .NET.
Parametri degli attributi
Diversi attributi dispongono di parametri, che possono essere posizionali, senza nome o denominati. I parametri posizionali devono essere specificati in un determinato ordine e non possono essere omessi. I parametri denominati sono facoltativi e possono essere specificati in qualsiasi ordine. I parametri posizionali vengono specificati per primi. I tre attributi seguenti, ad esempio, sono equivalenti:
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
Il primo parametro, ovvero il nome della DLL, è posizionale ed è sempre specificato per primo. Gli altri parametri sono denominati. In questo caso, entrambi i parametri denominati sono impostati automaticamente su false e possono quindi essere omessi. I parametri posizionali corrispondono ai parametri del costruttore dell'attributo. I parametri denominati o facoltativi corrispondono a proprietà o campi dell'attributo. Per informazioni sui valori predefiniti dei parametri, fare riferimento alla documentazione di ciascun attributo.
Per altre informazioni sui tipi di parametro consentiti, vedi la sezione Attributi della specifica del linguaggio C#
Destinazioni degli attributi
La destinazione di un attributo è l'entità a cui tale attributo viene applicato. Un attributo, ad esempio, può essere applicato a una classe, a un metodo particolare o a un intero assembly. Per impostazione predefinita, un attributo viene applicato all'elemento che lo segue. È tuttavia possibile identificare in modo esplicito, ad esempio, se un attributo viene applicato a un metodo, al relativo parametro o al relativo valore restituito.
Per identificare in modo esplicito la destinazione di un attributo, usare la sintassi seguente:
[target : attribute-list]
Nella tabella seguente sono elencati i possibili valori di target
.
Valore target | Si applica a |
---|---|
assembly |
Intero assembly |
module |
Modulo di assembly corrente |
field |
Campo in una classe o uno struct |
event |
Evento |
method |
Metodo o funzioni di accesso alle proprietà get e set |
param |
Parametri del metodo o parametri della funzione di accesso alla proprietà set |
property |
Proprietà |
return |
Valore restituito di un metodo, un indicizzatore di proprietà o una funzione di accesso alla proprietà get |
type |
Struct, classe, interfaccia, enumeratore o delegato |
È necessario specificare il valore di destinazione field
per applicare un attributo al campo sottostante creato per una proprietà implementata automaticamente.
Nell'esempio seguente viene illustrato come applicare attributi ad assembly e moduli. Per altre informazioni, vedere Attributi comuni (C#).
using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]
Nell'esempio seguente viene illustrato come applicare gli attributi a metodi, parametri di metodo e valori restituiti dal metodo in C#.
// default: applies to method
[ValidatedContract]
int Method1() { return 0; }
// applies to method
[method: ValidatedContract]
int Method2() { return 0; }
// applies to parameter
int Method3([ValidatedContract] string contract) { return 0; }
// applies to return value
[return: ValidatedContract]
int Method4() { return 0; }
Nota
Indipendentemente dalle destinazioni in cui l'oggetto ValidatedContract
è definito come valido, è necessario specificare la destinazione return
, anche se ValidatedContract
viene definito in modo da essere valido solo per i valori restituiti. In altre parole, il compilatore non usa le informazioni AttributeUsage
per risolvere le destinazioni degli attributi ambigue. Per altre informazioni, vedi AttributeUsage.
Usi comuni degli attributi
Di seguito vengono elencati alcuni degli usi comuni degli attributi nel codice:
- Contrassegno dei metodi mediante l'attributo
WebMethod
nei servizi Web per indicare che è possibile chiamare il metodo tramite il protocollo SOAP. Per ulteriori informazioni, vedere WebMethodAttribute. - Descrizione della procedura di marshalling dei parametri del metodo durante l'interazione con il codice nativo. Per ulteriori informazioni, vedere MarshalAsAttribute.
- Descrizione delle proprietà COM per classi, metodi e interfacce.
- Chiamata al codice non gestito che usa la classe DllImportAttribute.
- Descrizione dell'assembly con indicazione di titolo, versione, descrizione o marchio.
- Descrizione dei membri della classe da serializzare per la persistenza.
- Descrizione della procedura di mapping tra membri di una classe e nodi XML per la serializzazione XML.
- Descrivere i requisiti di sicurezza per i metodi.
- Definizione delle caratteristiche usate per garantire la sicurezza.
- Controllo delle ottimizzazioni tramite il compilatore JIT (Just-In-Time), in modo da garantire un semplice debug del codice.
- Recupero di informazioni relative al chiamante di un metodo.
Panoramica della reflection
La reflection è utile nelle situazioni seguenti:
- Quando è necessario accedere agli attributi nei metadati del programma. Per altre informazioni, vedere Recupero di informazioni memorizzate negli attributi.
- Per esaminare e creare istanze di tipi in un assembly.
- Per creare nuovi tipi in fase di esecuzione. Usare le classi in System.Reflection.Emit.
- Per eseguire l'associazione tardiva, accedere ai metodi per i tipi creati in fase di esecuzione. Vedi l’articolo Caricamento e uso dinamico dei tipi.
Sezioni correlate
Per altre informazioni: