martes, 3 de junio de 2014

Receta No. 3-10 en C#: Obtención de Información de Tipos (Reflection)

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Operador typeof
3.1.1 Uso de MethodInfo
3.2 Uso método GetNestedTypes
3.3 Otros métodos alternativos para obtener una instancia Type
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

Esta es una nueva y gran oportunidad para ir más a fondo del concepto de reflection. Veremos que este concepto brinda al programador la posibilidad de desarrollar en términos dinámicos sobre el lenguaje de programación C#. Esto abre grandes oportunidades para el tratamiento de tipos y miembros de tipo de manera flexible, por ejemplo, que podamos conocer los miembros de un tipo en particular y consultar su informa; inclusive, poder crear instancias a partir de la meta-información asociada al tipo; todo lo anterior en tiempo de ejecución. ¡Empecemos!

1. Problema

Estamos buscando un método que nos permita obtener la información (meta-información): métodos, propiedades, campos, constructores, etc. de los tipos definidos en el modelo del mundo del problema de una de las aplicaciones que tenemos para pruebas. El propósito ese entender este concepto de consulta de la información asociada a los tipos para empezar a plantearnos la idea de desarrollar de forma dinámica.

2. Solución

Consultando la biblioteca (MSDN) de Microsoft .NET Framework, hemos encontrado que la obtención de una (o un arreglo) instancia del tipo System.Type permite consultar la meta-información de los tipos del modelo.

3. Discusión de la Solución

En [1] nos ofrecen la siguiente vista general de formas de obtención del tipo System.Type:
  • Uso del operador typeof.
  • Invocar al método static GetType de la clase System.Type.
  • Invocar el método GetType sobre una instancia de un tipo específico.
  • Usar métodos de obtención de tipos anidados (cfr. Tipos Anidados en C#):
    • GetNestedType, o
    • GestNestedTypes
  • Invocar uno de los métodos de la clase Assembly [4]:
    • GetType, o
    • GetTypes
  • Uso de los métodos de la clase System.Reflection.Module [5]:
    • GetType, o 
    • GetTypes, o 
    • FindTypes
En la secciones sub-siguientes exploraremos varios de estos métodos: concepto, uso, y ejemplos.

3.1 Operador typeof

Al operador typeof [6] se le puede considerar una palabra clave para la obtención del tipo (junto con su meta-información) sobre una instancia de la clase System.Type [7]. Su uso consiste básicamente en especificar entre paréntesis un tipo de dato integrado o cualquiera definido por el programador. Por ejemplo:

System.Type tipo = typeof(double);

Observe que con la expresión del lado derecho, hemos especificado el tipo a obtener: double.  Esto también lo podemos hacer en tiempo de ejecución con cualquier instancia de un tipo. Así:

double pi = Math.PI;

System.Type type = pi.GetType();


typeof también nos puede servir para obtener la información de los tipos genéricos (cfr. Tipos Genéricos en C#):

Type tipoGenerico = typeof(Dictionary<,>);

Veamos un ejemplo de uso de este método:

Archivo de código fuente Usotypeof.cs [enlace alternativo]:
En la línea 16 obtenemos una instancia de la clase System.Type con la meta-información del tipo (clase) ClaseEjemplo. Enseguida, en la línea 20, a través del método GetMethods [9, 10] (System.Type) obtenemos un arreglo elementos MethodInfo [11] con la información de los métodos public (heredados y propios) de la clase `ClaseEjemplo`. A partir de la línea 24 hasta la línea 27 se implementa la lógica para enumerar cada uno de los elementos del arreglo metodosClaseEjemplo.

Más adelante, en la línea 31, creamos un arreglo con elementos MemberInfo [12].

> Prueba de ejecución.

Resultado:
Ejecución prueba del operador typeof
Figura 1. Ejecución prueba del operador typeof.

3.1.1 Uso de MethodInfo

La clase MethodInfo permite obtener la información (tanto los atributos de la firma del método, como también su meta-información) de los métodos de un tipo.

El ejemplo que viene a continuación tiene como propósito extender la compresión de obtención de los miembros de la sección inmediatamente anterior.

Archivo de código fuente UsoGetMethodInfo.cs [enlace alternativo]:

La clase UsoGetMethodInfo posee los siguientes miembros:
  • MetodoA(int i, int j)
  • MetodoA(int[] i)
  • MetodoA(int* i)
  • MetodoA(ref int r)
  • MetodoA( int i, out int o)
La información de estos métodos es obtenida en tiempo de ejecución, a través del método GetMethod [13] usuado a lo largo de las líneas 26-50.

Compilación:


  1. csc /unsafe /target:exe UsoGetMethodInfo.cs

Resultado:
Ejecución prueba del método GetMethod de la clase MethodInfo
Figura 2. Ejecución prueba del método GetMethod de la clase MethodInfo.

3.2 Uso método GetNestedTypes

Con el método GetNestedTypes de la clase System.Type podemos obtener el conjunto de tipos anidados en un tipo específico. Esta es la firma [14]:

public Type[] GetNestedTypes()

Pasemos directamente al ejemplo:

Archivo de código fuente UsoGetNestedTypes.cs [enlace alternativo]:

En línea 20 creamos una instancia de Type para describir a la clase ClaseExterior. Con el método GetNestedTypes (línea 23) obtenemos un arreglo de elementos Type con los tipos anidados en la clase ClaseExterior.

Con el ciclo foreach enumeramos los tipos anidados en la clase mencionada (líneas 27-29).

> Prueba de ejecución.

Resultado:
Cantidad de tipos anidados en `ClaseExterior`: 2


Tipo anidado: Recetas.Cap03.ClaseExterior+EstructuraAnidada

Tipo anidado: Recetas.Cap03.ClaseExterior+ClaseAnidada

3.3 Otros métodos alternativos para obtener una instancia Type

En la Figura 3 se muestra un listado de métodos alternativos para la obtención de instancias Type:
Métodos de obtención instancias System.Type
Figura 3. Métodos de obtención instancias System.Type.

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

Pasemos a desarrollar y a entender otro ejemplo con uso extendido del operador typeof y el método GetType.

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


  1. csc /target:exe UsoGetType.cs

Resultado:
Resultado del uso del método GetType de Object
Figura 4. Resultado del uso del método GetType de Object.

5. Conclusiones

Hemos comprendido acerca del proceso de obtención de los atributos de métodos, y la meta-información de los mismos y de tipos. En los ejemplos apreciamos la utilidad de los métodos GetType (de la clase Type, y de Object), el operador typeof, y otras formas de obtener la meta-información de tipos.

6. Glosario

  • Meta-información
  • Reflection
  • Type

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]: Comprobación de  Tipos en Tiempo de Compilación y Ejecución en C# - http://ortizol.blogspot.com/2014/03/comprobacion-de-tipos-en-tiempo-de.html
[3]: Tipos Anidados en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/05/tipos-anidados-en-c.html
[4]: Assembly Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.assembly(v=vs.110).aspx
[5]: Module Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.module(v=vs.110).aspx
[6]: typeof (C# Reference) - http://msdn.microsoft.com/en-us/library/58918ffs.aspx
[7]: Type Class (System) - http://msdn.microsoft.com/en-us/library/system.type(v=vs.110).aspx
[8]: How to: Examine and Instantiate Generic Types with Reflection - http://msdn.microsoft.com/en-us/library/b8ytshk6(v=vs.110).aspx
[9]: Type.GetMethods Method (System) - http://msdn.microsoft.com/en-us/library/system.type.getmethods(v=vs.110).aspx
[10]: Type.GetMethods Method (System) - http://msdn.microsoft.com/en-us/library/td205ybf(v=vs.110).aspx
[11]: MethodInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo(v=vs.110).aspx
[12]: MemberInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo(v=vs.110).aspx
[13]: Type.GetMethod Method (String, Type[]) (System) - http://msdn.microsoft.com/en-us/library/6hy0h0z1(v=vs.110).aspx
[14]: Type.GetNestedTypes Method (System) - http://msdn.microsoft.com/en-us/library/266a0de6(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

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