Marco Besteiro y Miguel Rodríguez

Marco Besteiro y Miguel Rodríguez Atributos Attributes. El lenguaje C# permite al programador especificar información declarativa (atributos) de ent

6 downloads 23 Views 103KB Size

Recommend Stories


Marco Contextual y Estratégico
Introducción La administración y gestión del recurso humano es un tema que involucra los diversos ámbitos de acción institucionales y que, entre otros

MARCO FISCAL Y PLAN FINANCIERO
MARCO FISCAL Y PLAN FINANCIERO La Ley 819 de 2003 define lo que es el marco fiscal de mediano plazo, el cual propende por alcanzar la transparencia fi

México MARCO INSTITUCIONAL Y JURIDICO
México MARCO INSTITUCIONAL Y JURIDICO Convenios de cooperación educativa y cultural entre México y otros países Albania, Ciudad de México, 27/10/1989

MARCO DE REFERENCIA COMITÉ DE PROYECTOS DE GRADO. Introducción Marco teórico Marco conceptual Marco legal
Introducci´ on Marco te´ orico Marco conceptual Marco legal MARCO DE REFERENCIA ´ DE PROYECTOS DE GRADO COMITE 2012 ´ DE PROYECTOS DE GRADO COMITE

Story Transcript

Marco Besteiro y Miguel Rodríguez

Atributos

Attributes. El lenguaje C# permite al programador especificar información declarativa (atributos) de entidades definidas en el código. Un ejemplo de esto son los modificadores de accesibilidad (public, protected, internal y private) que permiten indicar desde dónde puede utilizarse un método (visibilidad del método). C# permite también definir nuevos tipos de información declarativa (atributos definidos por el usuario) para varias entidades de programación y también permite obtener esa información en tiempo de ejecución. Por ejemplo, podría definirse el atributo InfoAttribute, el cual puede ser utilizado en clases y métodos para que los elementos del programa puedan acceder a la información sobre esas clases y métodos. Se puede decir que un atributo es un tipo de datos -una clase- que se puede utilizar para “decorar” a otras clases o elementos -métodos, variables...-. Los atributos se guardan con los datos y puesto que ofrecen información sobre éstos se les llama metadatos. Tal información se guarda en tiempo de compilación, en el assembly, junto a los datos y puede ser consultada durante la ejecución.

La clase System.Attribute Todos los atributos derivan directa o indirectamente de esta clase heredando ciertas características. En realidad podría utilizarse como atributo cualquier tipo definido por el usuario, pero es mejor utilizar tipos derivados de System.Attribute. -

Los atributos pueden ser asociados a distintos elementos: Nombre de elemento Descripción El atributo puede ser aplicado a cualquier elemento. Assembly El atributo puede ser aplicado a un assembly. Class El atributo puede ser aplicado a una clase. ClassMembers El atributo puede ser aplicado a clases, structuras, enumeraciones, constructores, métodos, propiedades, campos, eventos, delegates e interfaces. Constructor El atributo puede ser aplicado a un constructor. Delegate El atributo puede ser aplicado a un delegate. Enum El atributo puede ser aplicado a una enumeration. Event El atributo puede ser aplicado a un evento. Field El atributo puede ser aplicado a un campo. Interface El atributo puede ser aplicado a un interface. Method El atributo puede ser aplicado a un método. Module El atributo puede ser aplicado a un module. Parameter El atributo puede ser aplicado a un parámetro. Property El atributo puede ser aplicado a una propiedad. ReturnValue El atributo puede ser aplicado a un valor de retorno. Struct El atributo puede ser aplicado a un tipo valor. All

1/14

Marco Besteiro y Miguel Rodríguez

Atributos

Tabla 12.1 -

Los atributos pueden ser heredados o no por un elemento derivado. Se puede decidir si se permite o no múltiples instancias de un atributo en el mismo elemento.

Los compiladores y demás herramientas de desarrollo utilizan esta información para identificar de qué tipo son los atributos personalizados que encuentran en el código. Los atributos personalizados pueden almacenarse con cualquier elemento de los metadatos, de este modo es posible almacenar información sobre la aplicación en tiempo de compilación y acceder a ésta en tiempo de ejecución o cuando otra herramienta lee los metadatos. A continuación se muestra un ejemplo de utilización de una clase atributo (InfoAttribute) y la propia clase. ... ... //El atributo Info corresponde a la clase InfoAttribute //se está aplicando a la clase CSaludar [Info("20/09/2001", Informacion = "Esta clase posee dos métodos, el constructor y Saludar")] public class CSaludar { private string nombre; public CSaludar(string nombre) { this.nombre = nombre; } public void Saludar() { System.Console.WriteLine("Hola " + nombre); } }

... ... La clase correspondiente es InfoAttribute: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] public class InfoAttribute : Attribute { private DateTime fecha; public string informacion; public InfoAttribute(string fecha) { this.fecha = DateTime.Parse(fecha); } public string Informacion { get { return informacion; }

2/14

Marco Besteiro y Miguel Rodríguez

Atributos

set { informacion = value; } } public DateTime Fecha { get { return fecha; } } }

Se puede observar que InfoAttribute tiene dos campos, fecha e información

Parámetros posicionales y con nombre. Un parámetro posicional de un tipo Attribute se define mediante un constructor público de tal tipo. Un parámetro con nombre se define mediante una propiedad de lectura-escritura no static. La diferencia entre ambos tipos de parámetros esque el primero sólo tiene método get, de modo que la única manera de establecerlo es mediante el constructor de la clase atributo. En el ejemplo anterior, fecha es un parámetro posicional e Información es un parámetro con nombre. Es muy sencillo apreciar la diferencia cuando se utiliza el atributo, los parámetros posicionales se pasan directamente al constructor del atributo y los parámetros con nombre se pasan indicando el nombre. [Info("20/09/2001", Informacion = "Esta clase posee dos métodos, el constructor y Saludar")] public class CSaludar {

… … }

Atributos reservados. En el ejemplo estudiado, la clase InfoAttribute ha sido creada por el desarrollador. Además de la posibilidad de que el desarrollador cree sus propias clases Attribute existe la posibilidad de que utilice clases Attribute ya definidas en el Framework .NET. A los atributos de tales clases se les llama atributos reservados.

ConditionalAttribute. Permite la definición de métodos condicionales, es decir, métodos a los que sólo se compilarán llamadas en función de una condición.

3/14

Marco Besteiro y Miguel Rodríguez

Atributos

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class ConditionalAttribute: System.Attribute { public ConditionalAttribute(string conditionalSymbol) {…} public string ConditionalSymbol { get {…} } }

Un método condicional está sujeto a las siguientes restricciones: -

Debe ser un método en una declaración de clase. Si fuese de un interface se daría un error en tiempo de compilación. El tipo devuelto por el método condicional ha de ser void. El método condicional no debe estar marcado con el modificador override (sí con virtual). El método condicional no debe ser una implementación de un método de un interface. Si lo es se dará un error de compilación. El método condicional no debe ser utilizado en una expresión de creación de un delegate. Si se utiliza se dará un error en tiempo de compilación.

Ejemplo: En el siguiente ejemplo su muestran tres clases (Clase1, Clase2 y Clase3). Clase1 define un método condicional, Clase2 invoca tal método teniendo la condición definida y Clase3 lo invoca con la condición sin definir. //Fichero Clase1.cs using System; //Para utilizar Conditional es necesario //el namespace System.Runtime.InteropServices using System.Diagnostics; namespace Clases_NameSpace { public class Clase1 { //Sólo se compilara una llamada a FunDebug //si está definido DEPURACION [Conditional("DEPURACION")] public static void FunDebug() { System.Console.WriteLine("Clase1.FunDebug ha sido llamada"); } } } //Fichero Clase2.cs #define DEPURACION using System; namespace Clases_NameSpace { public class Clase2 { public static void FunClase2 () {

4/14

Marco Besteiro y Miguel Rodríguez

Atributos

System.Console.WriteLine("Se va a intentar llamar a Clase1.FunDebug desde Clase2.FunClase2"); // se llama a FunDebug Clase1.FunDebug(); } } } //Fichero Clase3.cs #undef DEPURACION using System; namespace Clases_NameSpace { class Clase3 { public static void FunClase3 () { System.Console.WriteLine("Se va a intentar Clase1.FunDebug desde Clase3.FunClase3"); // no se llama a FunDebug Clase1.FunDebug(); } } } //Fichero PruebaAtributosReservados.cs using System; using System.Reflection; using Clases_NameSpace; class PruebaAtributosReservados { public static void Main() { Clase2.FunClase2 (); Clase3.FunClase3 (); System.Console.WriteLine(" "); } }

El resultado de ejecutar el ejemplo será:

5/14

llamar

a

Marco Besteiro y Miguel Rodríguez

Atributos

Figura 12.1

ObsoleteAttribute. Se utiliza para marcar elementos que no debieran ser utilizados en adelante. [AttributeUsage(AttributeTargets.All)] public class ObsoleteAttribute: System.Attribute { public ObsoleteAttribute(string message) {…} public string Message { get {…} } public bool IsError{ get {…} set {…} } }

Si en el ejemplo anterior se modifica el método FunDebug de Clase1 añadiendo el atributo Obsolete, se tendrá: using System; //Para utilizar Conditional y Obsolete es necesario //el namespace System.Runtime.InteropServices using System.Diagnostics; namespace Clases_NameSpace { public class Clase1 { //Sólo se compilara una llamada a FunDebug //si está definido DEPURACION [Conditional("DEPURACION")] [Obsolete("FunDebug va a ser sustituida por otra función, no la utilice")] public static void FunDebug() { System.Console.WriteLine("Clase1.FunDebug ha sido llamada"); } } }

6/14

Marco Besteiro y Miguel Rodríguez

Atributos

Este ejemplo afecta a la compilación, el resultado será que el compilador mostrará un warning por cada intento de utilizar el método FunDebug . Se puede observar en la Clase1.FunDebug añadida al fichero figura 12.2 la llamada a PruebaAtributosReservados.cs.

Figura 12.2

DllImportAttribute. No siempre se puede conseguir lo que se desea con la librería de clases base .NET. En tales ocasiones puede ser necesario acceder al API de Windows, es decir, a funciones contenidas las librerías de enlace dinámico (dll) de tipo Win32. En el siguiente ejemplo se añadirá una llamada a la función MessageBox desde la clase PruebaAtributosReservados. using System; using System.Reflection; using Clases_NameSpace; //Para utilizar DllImport es necesario el namespace //System.Runtime.InteropServices using System.Runtime.InteropServices; class PruebaAtributosReservados { [DllImport("User32.dll")] public static extern int MessageBox(int hParent, string Message, string Caption, int Type);

7/14

Marco Besteiro y Miguel Rodríguez

Atributos

public static void Main() { Clase2.FunClase2 (); Clase3.FunClase3 (); System.Console.WriteLine(" "); System.Console.WriteLine("Para llamar a MessageBox pulse Enter: "); System.Console.ReadLine(); MessageBox(0, "Hola desde el API de Windows", "Mensaje invocado desde .NET", 0); } }

El resultado de ejecutar este ejemplo será:

Figura 12.3 Tras pulsar Enter se mostrará el cuadro de mensaje:

Figura 12.4

StructLayoutAttribute. Este atributo permite indicar el alineamiento (struct layout) de los miembros de una clase o estructura. El alineamiento de los miembros de una clase o estructura determina el tamaño que ocupa cada miembro (por ejemplo, si se la línea a 4 bytes, todos los miembros de una estructura o clase han de ocupar múltiplos de 4 bytes) y en consecuencia, también

8/14

Marco Besteiro y Miguel Rodríguez

Atributos

determina el desplazamiento u offset de cada miembro de la clase o estructura respecto del comienzo de la clase o estructura.

CLSCompliantAttribute. Indica si un elemento de un programa cumple la CLS (Common Languaje Specification), es decir, si es compatible con el lenguaje común de la plataforma .NET. Por defecto, un elemento al que no se haya aplicado el atributo CLSCompliant: -

Se considera que el assembly no cumple la especificación de lenguaje común (CLS). Se considera que el tipo cumple la CLS si el tipo que lo contiene o el assembly cumple la CLS. Se considera que un miembro de un tipo cumple la CLS sólo si la cumple el tipo al que pertenece.

Si un assembly se marca como CLSCompliant, cualquier tipo público del assembly que no sea CLSCompliant debe ser marcado con el atributo CLSCompliant pasándole False como argumento. Del mismo modo, en una clase marcada como CLSCompliant han de marcarse como no CLSCompliant todos los miembros que no sean CLSCompliant. Todos los miembros que no sean CLSCompliant debieran tener alternativas CLSCompliant.

SerializableAttribute y NonSerializableAttribute. Estos atributos se utilizan para indicar que una clase y/o los miembros de una clase son o no serializables. La serialización permite programar cómodamente qué datos de una clase se envían a un flujo. Un flujo es un concepto que puede asociarse a un fichero, a la red, etc... No debe utilizarse el atributo Serializable con clases que contengan punteros, handles u otras estructuras de datos que no puedan ser reconstruidos al deserializarlos en un entorno diferente (por ejemplo, los punteros tienen sentido en el proceso al que pertenecen pero fuera de los límites del proceso al que pertenecen, la dirección a la que apuntan no es válida).

AttributeUssageAttribute. Este atributo se utiliza para describir el modo en que puede ser utilizado un atributo. Una clase decorada con este atributo debe derivar de System.Attribute directa o indirectamente. En caso de no ser así se dará un error de compilación. El atributo AttributeUsage se utiliza para crear nuevas clases de atributos, como ya se ha visto. La clase de tipo Attribute AttributeUsageAttribute es: [AttributeUsage(AttributeTargets.Class)] public class AttributeUsageAttribute: System.Attribute { public AttributeUsageAttribute(AttributeTargets validOn) {…} public AttributeUsageAttribute(AttributeTargets validOn, bool allowMultiple,

9/14

Marco Besteiro y Miguel Rodríguez

Atributos

bool inherited) {…} public virtual bool AllowMultiple { get {…} set {…} } public virtual bool Inherited { get {…} set {…} } public virtual AttributeTargets ValidOn { get {…} } } public enum AttributeTargets { Assembly = 0x0001, Module = 0x0002, Class = 0x0004, Struct = 0x0008, Enum = 0x0010, Constructor = 0x0020, Method = 0x0040, Property = 0x0080, Field = 0x0100, Event = 0x0200, Interface = 0x0400, Parameter = 0x0800, Delegate = 0x1000, All = Assembly | Module | Class Method | Property | Field Delegate, ClassMembers = Class | Struct Property | Field }

| Struct | Enum | Constructor | | Event | Interface | Parameter | | Enum | Constructor | Method | | Event | Delegate | Interface,

Atributos definidos por el usuario. Los atributos definidos por el desarrollador son, físicamente, clases derivadas de System.Attribute. Realmente no es obligatorio que deriven de System.Attribute pero sí recomendable.

Utilización de AttributeUsageAttribute. La utilización del atributo AttributeUsage es relativamente sencilla e implica los siguientes pasos: -

-

Crear la clase atributo. En esta fase se deberá crear la clase que luego servirá para decorar otras clases y se deberán configurar las propiedades AllowMultiple, Inherited y ValidOn de tal clase. Aplicar la clase atributo creada a otras clases (decorar). Obtener mediante reflexión (GetCustomAttributes...) los atributos de la clase decorada -durante la ejecución- y utilizarlos.

AllowMultiple. Es un parámetro con nombre. Indica si puede aplicarse más de una vez el mismo atributo a un elemento. Inherited. Es un parámetro con nombre. Especifica si el atributo puede ser heredado y sobrescritos sus métodos por clases derivadas.

10/14

Marco Besteiro y Miguel Rodríguez

Atributos

ValidOn. Es un parámetro posicional y sólo puede ser pasado al constructor de AttributeUsage. Especifica los elementos de un programa a los que puede aplicarse el atributo. En realidad, el conjunto de los posibles elementos a los que puede afectar el atributo es indicado por la enumeración AttributeTargets. Se pueden combinar varios valores de AttributeTargets con |. Los posibles valores de AttributeTargets son: Nombre de elemento Descripción All El atributo puede ser aplicado a cualquier elemento. Assembly El atributo puede ser aplicado a un assembly. Class El atributo puede ser aplicado a una clase. ClassMembers El atributo puede ser aplicado a clases, structuras, enumeraciones, constructores, métodos, propiedades, campos, eventos, delegates e interfaces. Constructor El atributo puede ser aplicado a un constructor. Delegate El atributo puede ser aplicado a un delegate. Enum El atributo puede ser aplicado a una enumeration. Event El atributo puede ser aplicado a un evento. Field El atributo puede ser aplicado a un campo. Interface El atributo puede ser aplicado a un interface. Method El atributo puede ser aplicado a un método. Module El atributo puede ser aplicado a un module. Parameter El atributo puede ser aplicado a un parámetro. Property El atributo puede ser aplicado a una propiedad. ReturnValue El atributo puede ser aplicado a un valor de retorno. Struct El atributo puede ser aplicado a un tipo valor. Tabla 12.2 Ejemplo: Creación y utilización de una clase atributo. Paso 1: Creación de la clase atributo InfoAttribute: La clase InfoAttribute estará contenida el la librería LibAtributos, en el fichero InfoAttribute.cs using System; namespace LibAtributos { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] public class InfoAttribute : Attribute { private DateTime fecha; public string informacion; public InfoAttribute(string fecha) {

11/14

Marco Besteiro y Miguel Rodríguez

Atributos

this.fecha = DateTime.Parse(fecha); } public string Informacion { get { return informacion; } set { informacion = value; } } public DateTime Fecha { get { return fecha; } } } }

Paso 2: Aplicación de la clase atributo a otra u otras clases. En este caso se creará una clase CSaludar dentro de una librería LibSaludar.dll. Se aplicará el atributo InfoAttribute a la clase CSaludar. El fichero donde está la clase CSaludar es CSaludar.cs. using System; using LibAtributos; namespace LibSaludar { //El atributo Info corresponde a la clase InfoAttribute //se está aplicando a la clase CSaludar [Info("20/09/2001", Informacion = "Esta clase posee dos métodos, el constructor y Saludar")] public class CSaludar { private string nombre; public CSaludar(string nombre) { this.nombre = nombre; } public void Saludar() { System.Console.WriteLine("Hola " + nombre); } } }

Paso 3: Crear una aplicación que, mediante la reflexión, obtenga la información que el atributo InfoAttribute asociada a la clase CSaludar. La aplicación será PruebaAtributos.exe. La clase aplicación se llama PruebaAtributos y está en el fichero PruebaAtributos.cs. using System;

12/14

Marco Besteiro y Miguel Rodríguez

Atributos

using System.Reflection; using LibAtributos; using LibSaludar; class PruebaAtributos { public static void Main() { Assembly as1 = Assembly.Load("LibSaludar"); //Obtener un array de referencias a todos los //tipos del assembly “LibSaludar”. //En este caso sólo hay uno: “CSaludar” Type[] tipos = as1.GetTypes(); foreach(Type tipo in tipos) { //Obtener un array de referencias a todos los //atributos de cada tipo del assembly “LibSaludar”, //es decir, de “CSaludar” //En este caso sólo hay un atributo: “InfoAttribute” Attribute[] atributos = Attribute.GetCustomAttributes(tipo); foreach(Attribute atributo in atributos) { //Obtener la información de “InfoAttribute” //y mostrarla //”InfoAttribute” tiene dos campos: //”Fecha” e “Información”. InfoAttribute info = atributo as InfoAttribute; System.Console.WriteLine("Clase: " + tipo.Name); System.Console.WriteLine("-----"); System.Console.WriteLine("Fecha: " + info.Fecha); System.Console.WriteLine("Información: " + info.Informacion); System.Console.WriteLine("-----"); System.Console.WriteLine(" "); } } } }

El resultado de ejecutar este ejemplo será:

13/14

Marco Besteiro y Miguel Rodríguez

Atributos

Figura 12.5

14/14

Get in touch

Social

© Copyright 2013 - 2024 MYDOKUMENT.COM - All rights reserved.