Definición de nuevos atributos
Especificación del nombre del atributo
Se considera que un atributo es toda aquella clase que derive de System.Attribute. Por tanto, para definir un nuevo tipo de atributo hay que crear una clase que derive de ella. Por convenio, a este tipo de clases suele dárseles nombres acabados en Attribute, aunque a la hora de usarlas desde C# es posible obviar dicho sufijo. Un ejemplo de cómo definir un atributo llamado Ayuda es:
using System;
class AyudaAttribute:Attribute {}
|
Y ejemplos de cómo usarlo prefijando la definición de clases son:
[Ayuda] class A {}
[AyudaAttribute] class B {}
|
Puede darse la circunstancia de que se haya definido un atributo con un cierto nombre sin sufijo Attribute y otro que si lo tenga. Como es lógico, en ese caso cuando se use el atributo sin especificar el sufijo se hará referencia a la versión sin sufijo y cuando se use con sufijo se hará referencia a la versión con sufijo.
Especificación del uso de un atributo
Por defecto cualquier atributo que se defina puede preceder la definición de cualquier elemento del lenguaje. Si se desea limitar a qué definiciones puede preceder es necesario prefijar la clase que lo define con un atributo especial llamado System.AttributeUsage. Este atributo consta de los siguientes parámetros con nombre:
- AllowMultiple: Por defecto cada atributo sólo puede aparecer una vez prefijando a cada elemento. Dándole el valor true a este parámetro se considerará que puede aparecer múltiples veces.
- Inherited: Por defecto los atributos aplicados a una clase no son heredados en sus clases hijas. Dándole el valor true a este parámetro se consigue que sí lo sean.
Aparte de estos dos parámetros, AttributeUsage también puede contar con un parámetro opcional sin nombre que indique a qué tipos de definiciones puede preceder. Por defecto se considera que un atributo puede preceder a cualquier elemento, lo que es equivalente a darle el valor AttributeTargets.All a este parámetro. Sin embrago es posible especificar otras posibilidades dándole valores de la enumeración System.AttributeTargets, que son los que se recogen en la Tabla
08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F00520065006600340038003600360038003300310034003700000000
:
Valor de AttributeTargets |
Significa que el atributo puede preceder a... |
All |
Cualquier definición |
Assembly |
Definiciones de espacio de nombres, considerándose que el atributo se refiere al ensamblado en general. |
Module |
Definiciones de espacio de nombres, considerándose que el atributo se refiere al módulo en su conjunto. |
Class |
Definiciones de clases |
Delegate |
Definiciones de delegados |
Interface |
Definiciones de interfaces |
Struct |
Definiciones de estructuras |
Enum |
Definiciones de enumeraciones |
Field |
Definiciones de campos |
Method |
Definiciones de métodos |
Constructor |
Definiciones de constructores |
Property |
Definiciones de propiedades o indizadores |
Event |
Definiciones de eventos |
Parameter |
Definiciones de parámetros de métodos |
ReturnValue |
Definiciones de valores de retorno de métodos |
Tabla 9: Valores de AttributeTargets
Es posible combinar varios de estos valores mediante operaciones lógicas "or" (carácter | ) Por ejemplo, si queremos definir el atributo Ayuda anterior de modo que sólo pueda ser usado para prefijar definiciones de enumeraciones o de clases se haría:
[AttributeUsage(AttributeTargets.Class | AttributeTargetes.Enum)] class Ayuda:Attribute {}
|
Es importante resaltar que
AttributeUsage sólo puede incluirse precediendo definiciones de otros atributos (o sea, de clases derivadas de
System.Attribute)
Especificación de parámetros válidos
Se considera que los parámetros sin nombre que puede tomar un atributo son aquellos que se especifiquen como parámetros en el constructor del tipo que lo define, y que sus parámetros con nombre serán las propiedades y campos públicos, no estáticos y de lectura/escritura definidos en dicho tipo.
Un ejemplo de cómo definir el atributo Ayuda anterior de modo que tome un parámetro sin nombre con la URL que indique dónde encontrar la ayuda sobre el miembro o clase al que precede y un parámetro con nombre llamado Autor que indique quién es el autor de esa documentación es:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)] class Ayuda:Attribute { private string autor; private string url; public Ayuda(string URL) { url=URL; } public string Autor { set {autor = value;} get {return autor;} } }
|
Ejemplos de usos válidos de este atributo son:
[Ayuda("http://www.josan.com/Clases/A.html")] class A {}
[Ayuda("http://www.josan.com/Clases/B.html", Autor="José Antonio")] class B {} |
Los tipos válidos de parámetros, tanto con nombre como sin él, que puede tomar un atributo son: cualquier tipo básico excepto decimal y los tipos enteros sin signo, cualquier enumeración pública, System.Type o tablas unidimensionales de elementos de cualquiera de los anteriores tipos válidos.