Attributi
Gli attributi forniscono un metodo efficace per associare metadati o informazioni dichiarative, con codice (assembly, tipi, metodi, proprietà e così via). Dopo che un attributo è associato a un'entità programma, l'attributo può essere sottoposto a query in fase di esecuzione usando una tecnica denominata reflection .
Gli attributi hanno le proprietà seguenti:
- Gli attributi aggiungono metadati al programma. metadati sono informazioni sui tipi definiti in un programma. Tutti gli assembly .NET contengono un set specificato di metadati che descrivono i tipi e i membri di tipo definiti nell'assembly. È possibile aggiungere attributi personalizzati per specificare eventuali informazioni aggiuntive necessarie.
- È possibile applicare uno o più attributi a interi assembly, moduli o elementi di programma più piccoli, 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 o i metadati in altri programmi usando reflection.
Reflection fornisce oggetti (di tipo Type) che descrivono assembly, moduli e tipi. È possibile utilizzare 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 si usano attributi nel codice, la reflection consente di accedervi. Per altre informazioni, vedere Attributi.
Ecco un semplice esempio di reflection usando il metodo GetType() , ereditato da tutti i tipi dalla classe base Object
, per ottenere il tipo di una variabile:
Nota
Assicurarsi di aggiungere using System;
e using System.Reflection;
nella parte superiore del file di .cs.
// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
L'output è: System.Int32
.
Nell'esempio seguente viene utilizzata 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 C# protected
e internal
non hanno alcun significato nel linguaggio intermedio (IL) e non vengono usate nelle API di reflection. I termini corrispondenti in IL sono Family e Assembly. Per identificare un metodo internal
tramite reflection, utilizzare la proprietà IsAssembly. Per identificare un metodo protected internal
, usare il IsFamilyOrAssembly.
Uso degli attributi
Gli attributi possono essere inseriti in quasi qualsiasi dichiarazione, anche se un attributo specifico potrebbe limitare i tipi di dichiarazioni su cui è valido. In C# si specifica un attributo inserendo il nome dell'attributo racchiuso tra parentesi quadre ([]
) sopra la dichiarazione dell'entità a cui si applica.
In questo esempio, 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 viene dichiarato come nell'esempio seguente:
[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();
È possibile inserire più attributi in una dichiarazione 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 determinata entità. Un esempio di attributo multiuso di questo tipo è ConditionalAttribute:
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
Nota
Per convenzione, tutti i nomi degli attributi terminano con la parola "Attribute" per distinguerli da altri elementi nelle librerie .NET. Tuttavia, non è necessario specificare il suffisso dell'attributo quando si usano attributi nel codice. Ad esempio, [DllImport]
equivale a [DllImportAttribute]
, ma DllImportAttribute
è il nome effettivo dell'attributo nella libreria di classi .NET.
Parametri dell'attributo
Molti attributi hanno parametri, che possono essere posizionali, senza nome o denominati. Tutti 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. Ad esempio, questi tre attributi sono equivalenti:
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
Il primo parametro, il nome della DLL, è posizionale e viene sempre prima; gli altri sono denominati. In questo caso, entrambi i parametri denominati hanno valore predefinito su false, in modo che possano 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 dei parametri predefiniti, vedere la documentazione dell'attributo singolo.
Per altre informazioni sui tipi di parametro consentiti, vedere la sezione attributi della specifica del linguaggio C# .
Destinazioni degli attributi
Il target di un attributo è l'entità a cui si applica l'attributo. Ad esempio, un attributo può essere applicato a una classe, a un metodo specifico o a un intero assembly. Per impostazione predefinita, un attributo si applica all'elemento che lo segue. Tuttavia, è anche possibile identificare in modo esplicito, ad esempio, se un attributo viene applicato a un metodo o al relativo parametro o al relativo valore restituito.
Per identificare in modo esplicito una destinazione dell'attributo, usare la sintassi seguente:
[target : attribute-list]
L'elenco dei possibili valori target
è illustrato nella tabella seguente.
Valore di destinazione | Si applica a |
---|---|
assembly |
Intero assemblaggio |
module |
Modulo corrente di assemblaggio |
field |
Campo in una classe o in una struttura |
event |
Evento |
method |
Funzioni di accesso alle proprietà di metodo o get set e di set |
param |
Parametri del metodo o parametri della funzione di accesso alle proprietà set |
property |
Proprietà |
return |
Valore restituito di un metodo, di un indicizzatore di proprietà o di una funzione di accesso alla proprietà get |
type |
Struct, classe, interfaccia, enumerazione o delegato |
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 agli assembly e ai 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 attributi a metodi, parametri del 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 ValidatedContract
è definito come valido, è necessario specificare la destinazione return
, anche se ValidatedContract
sono stati definiti per essere applicati solo ai valori restituiti. In altre parole, il compilatore non userà le informazioni AttributeUsage
per risolvere ambiguità nei bersagli degli attributi. Per altre informazioni, vedere AttributeUsage.
Usi comuni per gli attributi
L'elenco seguente include alcuni degli usi comuni degli attributi nel codice:
- Contrassegnare i metodi usando l'attributo
WebMethod
nei servizi Web per indicare che il metodo deve essere chiamabile tramite il protocollo SOAP. Per altre informazioni, vedere WebMethodAttribute. - Descrizione di come gestire il marshalling dei parametri di un metodo nell'interoperabilità con codice nativo. Per altre informazioni, vedere MarshalAsAttribute.
- Descrizione delle proprietà COM per classi, metodi e interfacce.
- Chiamata di codice non gestito tramite la classe DllImportAttribute.
- Descrizione dell'assembly in termini di titolo, versione, descrizione o marchio.
- Descrizione dei membri di una classe da serializzare per la persistenza.
- Descrizione di come eseguire il mapping tra i membri della classe e i nodi XML per la serializzazione XML.
- Descrizione dei requisiti di sicurezza per i metodi.
- Specifica delle caratteristiche utilizzate per applicare la sicurezza.
- Controllare le ottimizzazioni dal compilatore JIT (Just-In-Time) in modo che il codice rimanga facile da eseguire.
- Recupero di informazioni sul chiamante di un metodo.
Panoramica della riflessione
La reflection è utile nelle situazioni seguenti:
- Quando è necessario accedere agli attributi nei metadati del programma. Per altre informazioni, vedere recupero di informazioni archiviate negli attributi.
- Per esaminare e creare istanze dei tipi in un assembly.
- Per la creazione di nuovi tipi in fase di esecuzione. Usare classi in System.Reflection.Emit.
- Per eseguire l'associazione tardiva, accedere ai metodi sui tipi creati in fase di esecuzione. Consulta l'articolo caricamento e uso dinamico dei tipi.
Sezioni correlate
Per altre informazioni: