Le classi attributo del Framework
Le classi attributo incluse nella tecnologia .NET
sono classi che derivano dalla classe base Attribute. Lo scopo di
queste classi è quello di aggiungere informazioni ad una classe (che chiameremo
target element
) allo scopo di
decorarla, di modificarne il comportamento a run-time
e di integrarla tramite meta-dati. Un attributo può essere applicato ad uno
qualsiasi degli elementi di cui è composto la nostra classe: la classe stessa,
un costruttore, un metodo, una proprietà, e così via. Lo stesso .NET
Framework fa un grande uso degli attributi: chi di voi ha partecipato ad
esempio allo workshop del 14 Luglio 2005, ha potuto vedere come Corrado ed Andrea hanno utilizzato gli attributi per creare Windows
Controls (il primo) e come creare propri attributi custom per migliorare - in certi casi - la leggibilità e la manutenibilità
del codice (il secondo).
Utilizzare un attributo significa marcare un certo elemento con il nome
dell'attributo stesso, seguito da eventuali parametri. Ad esempio, se stiamo
creando un Windows Control e vogliamo assegnare una description ad una
proprietà ben specifica, così da farla apparire nella Property Windows, il
codice sarebbe simile al seguente:
[Description("Indicare il peso del libro")]
public string Weight {
get { return _Weight; }
set { _Weight = value; }
}
In questo caso, abbiamo utilizzato la classe DescriptionAttribute,
abbreviata in Description per decorare la nostra classe, ed
informare il compilatore che quella proprietà dispone di una descrizione.
L'equivalente in VB.NET è il seguente:
'NON TESTATO:
sarà giusto? Eh Eh!
<Description("Indicare il peso del libro")> _
Public Property Weight As String
Get
Return _Weight
End Get
Set
_Weight = Value
End Set
End Property
Le classi attributo messe a disposizione dal framework sono davvero tante, ma
il metodo per utilizzarle è sempre lo stesso, ovvero indicarle prima del
target element racchiundendole negli opportuni marcatori, e
successivamente indicando uno o più parametri al costruttore. Non
dimentichiamoci infatti che un attributo non è nient'altro che una normalissima
classe, e quindi deve poter disporre di almeno un costruttore. Nei post in
futuro, vedremo l'utilizzo degli attributi soprattutto nel contesto della
serializzazione: decorando metodi e proprietà con gli attributi,
possiamo specificare al compilatore come vogliamo che la classe venga
serializzata in XML, aumentando le potenzialità che abbiamo di default.
Questa pagina su MSDN elenca gli attributi più
comunemente usati nei progetti VS2005.
Evidenzio solo i seguenti:
- AssemblyKeyFileAttribute, per assegnare uno
strong-name ad un assembly
- Obsolete, per ricordarci quando un certo
target element è antiquato ed avere un avviso
- Browsable, Category e DesignOnly, e tutte le altre associate alla creazione
di Windows Controls
- date un'occhiata al file AssemblyInfo.cs per vedere
attributi globali associati ad un assembly nella sue globalità
Le classi attributo custom
Creare una classe
derivandola dalla classe base System.Attribute significa voler creare un proprio attributo
custom. Lo scopo è ovviamente decorare una classe, e grazie ai metadati
assegnati, modificarne il comportamento. Ecco un esempio (testato solo con il
Framework 1.1) tratto dal mio blog, su come migliorare il comportamento della classe
PrintDocument. Utilizzando i classici meccanismi di Reflection (ed in particolare il metodo statico GetCustomAttributes), infatti, una classe può capire se
è stata decorata o meno da un certo attributo, e quindi agire in un modo
piuttosto che in un altro. Nel caso qui sopra, avevo creato una classe
AdvancedPrintDocument, derivata da PrintDocument, a cui avevo
assegnato un attributo custom Logo.
[Logo("K:\\Documenti\\Immagini\\Personali Igor\\blog_igor.jpg", 70, 200)]
public class AdvancedPrintDocument : System.Drawing.Printing.PrintDocument
{
...
...
}
La classe Logo non è nient'altro che una classe derivata da
System.Attribute e che dispone di un costruttore come quello utilizzato dal
codice sopra.