sábado, 7 de junio de 2014

Receta No. 3-14 en C#: Investigar los Atributos de un Elemento de Programa con Reflection

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Representates de elementos de programa
3.2 Método GetCustomAttributes
3.3 Método IsDefined
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En el ejemplo de la sección 4.2 de la receta 13 (Crear un Atributo Personalizado) se demostró acerca de la consulta de los atributos aplicados a un elemento de programa; aprovecharemos este conocimiento previo para extendernos a lo largo de esta receta. Aquí utilizaremos la interfaz ICustomAttributeProvider que implementa todos los elementos de programa (tipos y atributos), de esta manera a través del método IsDefined podemos investigar/consultar si un atributo ha sido aplicado a un elemento de programa.

1. Problema

Contamos con el conocimiento esencial para crear atributos personalizados y utilizarlos para decorar elementos de programa (tipos y miembros). Nos ha surgido una nueva necesidad y es la que consiste en encontrar un método de consulta de los meta-datos aplicados con los atributos personalizados.

2. Solución

Buscando en la bibliografía técnica y en los manuales de referencia del lenguaje de programación C#, encontramos que todos los elementos de programa implementan (aquellos que los representan, para precisar) la interfaz ICustomAttributeProvider; esta interfaz cuenta con el miembro IsDefined, con este método podemos determinar si un atributo ha sido aplicado a un determinado elemento de programa. Otro miembro útil de esta interfaz, es el método GetCustomeAttribures que exploraremos en la siguiente sección.

3. Discusión de la Solución

3.1 Representantes de elementos de programa

Las clases que representan elementos de programa, todas estas, implementan la interfaz ICustomAttributeProvider [2], i.e., [1]:
  • Assembly [3]
  • Module [4]
  • Type [5]
  • EventInfo [6]
  • FieldInfo [7]
  • PropertyInfo [8], y
  • MethodBase [9]
Esta última clase, posee dos subclases. A saber:
  • ConstructorInfo [10], y 
  • MethodInfo [11]
Todos estos tipos disponen de los métodos GetCustomAttributes [12] y IsDefined.

3.2 Método GetCustomAttributes

3.2.1 GetCustomAtributtes(bool)

La versión sobrecargada de GetCustomAttributes con firma [13]:

Object[] GetCustomAttributes(bool inherit)

Descripción puntual:
  • Tipo de retorno Object[]: arreglo de elementos object que contiene aquellos atributos personalizados creados por el usuario.
  • inherit: Cuando se pasa true como argumento, entonces busca en la jerarquía de herencia de los atributos personalizados (no incluye los atributos definidos en la biblioteca de clases de .NET Framework).

3.2.2 GetSutomAttributes(Type, bool)

Esta versión sobrecargada permite establecer un filtro con el parámetro Type en la generación del arreglo de elementos object solo con el tipo de atributo especificado. Firma [14]:

Object[] GetCustomAttributes(Type atributeType, bool inherit)

Descripción puntual:
  • Tipo de retorno Object[]: arreglo de elementos object que contiene aquellos atributos personalizados creados por el usuario.
  • atributeType: Filtro para la generación del arreglo de elementos object. Solo retornará los atributos del tipo especificado.
  • inherit: Cuando se pasa true como argumento, entonces busca en la jerarquía de herencia de los atributos personalizados (no incluye los atributos definidos en la biblioteca de clases de .NET Framework).
[Nota: En la sección 4.2 de la receta 13 (Crear un Atributo Personalizado) se incluye un ejemplo con el uso de este método. Recomiendo su consulta para afianzar el conocimiento adquirido aquí.]

3.3 Método IsDefined

El método IsDefined [14] permite consultar si un atributo ha sido aplicado en un tipo o miembro. Esta es la firma:

bool IsDefined(Type attributeType, bool inherit)

Descripción puntual:
  • attributeType: Representación Type del tipo de atributo personalizado a consultar.
  • inherit: Cuando se pasa true como argumento, entonces busca en la jerarquía de herencia de los atributos personalizados (no incluye los atributos definidos en la biblioteca de clases de .NET Framework).
Veamos este ejemplo con la versión de la clase Attribute:

Archivo de código fuente UsoIsDefined.cs [enlace alternativo]:
En las líneas 6-14 definimos el atributo personalizado ObsoletoAttribute. Lo aplicamos al método Metodo1 en la línea 19. En la línea 38 usamos el método IsDefined, al que le especificamos el nombre del miembro (representación Type), y el tipo que nos interesa comparar:

bool marcadoObsoleto = Attribute.IsDefined(infoMetodo, typeof (ObsoletoAttribute));

> Prueba de ejecución.

Resultado:
Uso método IsDefined de Attribute
Figura 1. Uso método IsDefined de Attribute.

4. Práctica: Código Fuente C#

En el siguiente ejemplo vamos a usar el método GetCustomAttributes con la versión sobrecargada definida en [14].

Archivo de código fuente AutorAttribute.cs [enlace alternativo]:
Compilación:


  1. csc /target:exe EnsambladorRegex.cs

Ejecución assembly:


  1. .\ConsultaAutorAttribute.exe

> Prueba de ejecución.

Resultado:

Nombre: Germán - Organización: OrtizOL
Nombre: Edward - Organización:

5. Conclusiones

Con los miembros IsDefine y GetCustomAttributes de la interfaz ICustomAttributeProperty pudimos consultar los atributos personalizados aplicados a un elemento de programa (tipo o miembro). Esto nos facilita en gran medida la aplicación de la ténica de reflection.

6. Glosario

  • Assembly
  • Reflection

7. Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: ICustomAttributeProvider Interface (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.icustomattributeprovider(v=vs.110).aspx
[3]: Assembly Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.assembly(v=vs.110).aspx
[4]: Module Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.module(v=vs.110).aspx
[5]: Type Class (System) - http://msdn.microsoft.com/en-us/library/system.type(v=vs.110).aspx
[6]: EventInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.eventinfo(v=vs.110).aspx
[7]: FieldInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo(v=vs.110).aspx
[8]: PropertyInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.propertyinfo(v=vs.110).aspx
[9]: MethodBase Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.methodbase(v=vs.110).aspx
[10]: ConstructorInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo(v=vs.110).aspx
[11]: MethodInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo(v=vs.110).aspx
[12]: ICustomAttributeProvider.GetCustomAttributes Method (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.icustomattributeprovider.getcustomattributes(v=vs.110).aspx
[13]: ICustomAttributeProvider.GetCustomAttributes Method (Boolean) (System.Reflection) - http://msdn.microsoft.com/en-us/library/b6xa75x5(v=vs.110).aspx
[14]: ICustomAttributeProvider.IsDefined Method (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.icustomattributeprovider.isdefined(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.