C# Atributos (Attribute)
Atributos (Attribute)Son etiquetas declarativas que se utilizan para transmitir información de comportamiento sobre varios elementos del programa (como clases, métodos, estructuras, enumeraciones, componentes, etc.) en tiempo de ejecución. Puede agregar información declarativa a un programa mediante el uso de atributos. Una etiqueta declarativa se describe colocando corchetes ([ ]) delante del elemento al que se aplica.
Los atributos (Attribute) se utilizan para agregar metadatos, como directivas de compilador y comentarios, descripciones, métodos, clases y otra información. El marco .Net proporciona dos tipos de atributos:predefinidosypersonalizadosatributos.
Especificar atributos (Attribute)
La sintaxis para especificar atributos (Attribute) es la siguiente:
[attribute(positional_parameters, name_parameter = value, ...)] element
El nombre y los valores del atributo (Attribute) se especifican entre corchetes, colocados antes del elemento al que se aplican. positional_parameters especifica la información requerida y name_parameter especifica la información opcional.
Atributos predefinidos (Attribute)
El marco .Net proporciona tres atributos predefinidos:
- AttributeUsage
- Conditional
- Obsolete
AttributeUsage
Atributo predefinidoAttributeUsageDescribe cómo usar una clase de atributo personalizado. Especifica los tipos de elementos a los que se puede aplicar el atributo.
La sintaxis para especificar este atributo es la siguiente:
[AttributeUsage( validon, AllowMultiple=allowmultiple, Inherited=inherited )]
Donde:
- El parámetro validon especifica los elementos de lenguaje en los que se puede colocar el atributo. Es un enumeradorAttributeTargetscombinación de valores. El valor predeterminado es AttributeTargets.All。
- Parámetroallowmultiple(Opcional) para la propiedadAllowMultipledel atributo (property), proporciona un valor booleano. Si es true, el atributo es multiuso. El valor predeterminado es false (de un solo uso).
- Parámetroinherited(Opcional) para la propiedadInheriteddel atributo (property), proporciona un valor booleano. Si es true, el atributo puede ser heredado por clases derivadas. El valor predeterminado es false (no se hereda).
Por ejemplo:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
Conditional
Este atributo predefinido marca un método condicional cuya ejecución depende del identificador de preprocesamiento especificado.
Causa la compilación condicional de las llamadas al método, dependiendo del valor especificado, comoDebugo Trace. Por ejemplo, muestra el valor de una variable al depurar código.
La sintaxis para especificar este atributo es la siguiente:
[Conditional( conditionalSymbol )]
Por ejemplo:
[Conditional("DEBUG")]
El siguiente ejemplo demuestra este atributo:
Ejemplo
using System;
using System.Diagnostics;
public class Myclass
{
[Conditional("DEBUG")]
public static void Message(string msg)
{
Console.WriteLine(msg);
}
}
class Test
{
static void function1()
{
Myclass.Message("In Function 1.");
function2();
}
static void function2()
{
Myclass.Message("In Function 2.");
}
public static void Main()
{
Myclass.Message("In Main function.");
function1();
Console.ReadKey();
}
}
Cuando el código anterior se compila y se ejecuta, produce el siguiente resultado:
In Main function. In Function 1. In Function 2.
Obsolete
Este atributo predefinido marca entidades de programa que no deben usarse. Le permite informar al compilador que descarte un elemento objetivo específico. Por ejemplo, cuando se usa un método nuevo en una clase pero aún desea mantener el método anterior en la clase, puede marcarlo como obsolete (obsoleto) mostrando un mensaje de que se debe usar el método nuevo en lugar del anterior.
La sintaxis para especificar este atributo es la siguiente:
[Obsolete( message )] [Obsolete( message, iserror )]
Donde:
- Parámetromessage, es una cadena que describe por qué el elemento está obsoleto y qué se debe usar en su lugar.
- Parámetroiserror, es un valor booleano. Si el valor es true, el compilador debe tratar el uso del elemento como un error. El valor predeterminado es false (el compilador genera una advertencia).
El siguiente ejemplo demuestra este atributo:
Ejemplo
public class MyClass
{
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod()
{
Console.WriteLine("It is the old method");
}
static void NewMethod()
{
Console.WriteLine("It is the new method");
}
public static void Main()
{
OldMethod();
}
}
Cuando intente compilar el programa, el compilador dará un mensaje de error que dice:
Don't use OldMethod, use NewMethod instead
Crear atributos personalizados (Attribute)
El marco .Net permite crear atributos personalizados para almacenar información declarativa que puede recuperarse en tiempo de ejecución. Según los estándares de diseño y las necesidades de la aplicación, esta información puede relacionarse con cualquier elemento objetivo.
La creación y el uso de atributos personalizados incluye cuatro pasos:
- Declarar atributos personalizados
- Construir atributos personalizados
- Aplicar atributos personalizados en elementos del programa objetivo
- Acceder a los atributos mediante reflexión
El último paso consiste en escribir un programa simple para leer metadatos y así encontrar varios símbolos. Los metadatos son datos e información que se utilizan para describir otros datos. El programa debe usar la reflexión para acceder a los atributos en tiempo de ejecución. Discutiremos esto en detalle en el próximo capítulo.
Declarar atributos personalizados
Un nuevo atributo personalizado debe derivarse deSystem.Attributela clase. Por ejemplo:
// 一个自定义特性 BugFix 被赋给类及其成员 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo : System.Attribute
En el código anterior, hemos declarado un atributo personalizado llamadoDeBugInfoatributo personalizado.
Construir atributos personalizados
Construyamos un atributo personalizado llamadoDeBugInfoatributo personalizado, que almacenará la información obtenida por el programa de depuración. Almacena la siguiente información:
- El número de código del bug
- El nombre del desarrollador que identificó el bug
- La fecha de la última revisión del código
- Un mensaje de cadena que almacena las marcas del desarrollador
NuestraDeBugInfoclase tendrá tres propiedades privadas (property) para almacenar las tres primeras informaciones y una propiedad pública (property) para almacenar el mensaje. Por lo tanto, el número de bug, el nombre del desarrollador y la fecha de revisión serán parámetros posicionales (positional) obligatorios de la clase DeBugInfo, y el mensaje será un parámetro opcional con nombre (named).
Cada atributo debe tener al menos un constructor. Los parámetros posicionales (positional) obligatorios deben pasarse a través del constructor. El siguiente código demuestraDeBugInfola clase:
Ejemplo
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
{
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d)
{
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo
{
get
{
return bugNo;
}
}
public string Developer
{
get
{
return developer;
}
}
public string LastReview
{
get
{
return lastReview;
}
}
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
Aplicar atributos personalizados
Aplique el atributo colocándolo inmediatamente antes de su objetivo:
Ejemplo
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle
{
// Variable miembro
protected double length;
protected double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012",
Message = "Return type mismatch")]
public double GetArea()
{
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display()
{
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
En el próximo capítulo, usaremos objetos de la clase Reflection para recuperar esta información.
Otras extensiones