sábado, 7 de junio de 2014

Receta No. 3-15 en C#: Uso Programático para Investigar y Descubrir los Miembros de un Tipo

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Método GetMembers
3.2 Método GetConstructors
3.3 Método GetMethods
3.4 Método GetProperties
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En esta receta utilizaremos métodos programáticos para obtener la información de los miembros declarados en un tipo (clase, interfaz, enumeración, evento, &c.) específico. Gracias a la técnica reflection, esto resulta fácil y eficiente gracias a los miembros definidos en la clase Type. (Recomiendo leer las tres recetas anteriores a esta: 3-13, 3-14, y 3-15.)

1. Problema

Queremos ir más a fondo, ahora necesitamos un métodos que nos permita enumerar los miembros de un tipo declarados en sí mismo. Sabemos que la clave es el uso de la técnica reflection, pero, ¿cuál es el artefacto de la biblioteca base de clases de Microsoft .NET Framework que permite solventar este requerimiento?

2. Solución

De cualquier tipo de la biblioteca de clases base de .NET Framework, e inclusive los propios definidos por el programados, podemos obtener su representación Type con cualquier de los medios que retornan una representación de este tipo:
  • System.Object.GetType()
  • Type.GetType (método sobrecargado)
  • Operador typeof
(En la sección 3.2 de la receta no. 3-12 (Crear un Objecto con Reflection) se muestra la ilustración gráfica de estos tres métodos de obtención de Type.)

Una vez que obtengamos la representación Type, ya podemos consultar (a través de reflection) los métodos, constructores, propiedades, eventos, etc., declarados en un tipo en particular.

3. Discusión de la Solución

Discutamos acerca de la obtención de los miembros de un tipo a través del uso de los métodos GetMembers, GetConstructors, GetMethods, y GetProperties.

3.1 Método GetMembers

El método GetMembers posee dos métodos sobrecargados [3]. El primero de ellos permite obtener la lista de todos los miembros public del tipo sobre el que se invoca este método. Esta es su firma [4]:

public MemberInfo[] GetMembers()

Descripción puntual:
  • Tipo de retorno MemberInfo[]: arreglo de elementos MemberInfo [5]. Las instancias MemberInfo contienen los meta-datos de los atributos o características de los miembros public de un tipo.
Ejemplo de uso:


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

En las líneas 6-14 declaramos la clase ClaseDemo con los miembros:
  • Campo entero,
  • Campo cadena,
  • Constructor ClaseDemo, y
  • Método Metodo
Más adelante, en la línea 23 creamos una instancia de ClaseDemo, enseguida declaramos un arreglo de elementos MemberInfo (línea 27); en la línea 31 obtenemos la representación Type a partir del método System.Object.GetType invocado desde la variable cd:

Type tipo = cd.GetType();


Ya en la línea 34 invocamos al métodos GetMembers declarados en la clase Type. Utilizamos un ciclo for (líneas 38-42) para enumerar todos los miembros de ClaseDemo.

> Prueba de ejecución.

Resultado:
Prueba ejecución de uso de método GetMembers
Figura 1. Prueba ejecución de uso de método GetMembers.

Por otro lado, podemos determinar las categorías de miembros con el propiedad MemberType [6] combinada con la enumeración MemberTypes [7], y aplicarlos en un bloque switch de la siguiente manera:

MemberInfo[] miembros = cd.GetMembers();

foreach (MemberInfo miembroInfo in miembros)
{
switch (miembroInfo.MemberType)
{
case MemberTypes.Constructor:
// Acciones...
break;
case MemberTypes.Field:
// Acciones...
break;
case MemberTypes.Method:
// Acciones:
break;
}
}

3.2 Método GetConstructors

El método GetConstructors posee dos versiones sobrecargadas [8]. La primera, la que posee cero parámetros, contiene esta firma [9]:

public ConstructorInfo[] GetConstructors()


Obtiene todos los constructores public definidos en al representación Type del tipo que le invoca.

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

Declaramos la clase ClaseDemo (líneas 6-12) con varias versiones sobrecargadas del constructor. En el código cliente, creamos un arreglo de elementos ConstructorInfo (línea 19). Usamos el operador typeof para crear la representación Type para la clase ClaseDemo e invocamos enseguida el método GetConstructors:

constructores = typeof(ClaseDemo).GetConstructors();

> Prueba de ejecución.

Resultado:

Constructores de `ClaseDemo`:
 Firma constructor: Void .ctor()
 Firma constructor: Void .ctor(Int32)
 Firma constructor: Void .ctor(Int32, String)
 Firma constructor: Void .ctor(Object[])

3.3 Método GetMethods

GetMethods posee la siguiente lista de métodos sobrecargados: [10]. Comprenderemos los esenciales de este método con la versión sobrecargada que posee cero argumentos [11]:

public MethodInfo[] GetMethods()

Descripción puntual:
  • Tipo de retorno MethodInfo[]: arreglo de elementos MethodInfo [12]. Representación de los meta-datos (atributos) de un método declarados en un tipo.
Archivo de código fuente UsoGetMethods.cs [enlace alternativo]:
En la línea 22 declaramos un arreglo de elementos MethodInfo [13]. Al arreglo anterior le asignamos una instancia de elementos MethodInfo con la invocación del método GetMethods de Type, así (línea 25):

metodos = typeof(ClaseDemo).GetMethods();

> Prueba de ejecución.

Resultado:

Conjunto de métodos de `ClaseDemo`:
 Firma método: Void MetodoA()
 Firma método: Void MetodoA(Int32)
 Firma método: Void MetodoB()
 Firma método: Boolean MetodoC(System.Object[])
 Firma método: Boolean Equals(System.Object)
 Firma método: Int32 GetHashCode()
 Firma método: System.Type GetType()
 Firma método: System.String ToString()

3.4 Método GetProperties

Con GetProperties de Type, obtenemos el conjunto de propiedades declaradas en un tipo. Conjunto de métodos sobrecargados en [14].


Exploremos la versión sobrecargada con cero-parámetros. Esta es su firma [15]:


public PropertyInfo[] GetProperties()

Descripción puntual:
  • Tipo de retorno PropertyInfo[]: Arreglo de elementos PropertyInfo [15].
Archivo de código fuente UsoGetProperties.cs [enlace alternativo]:

Sobre la línea 11 declaramos un arreglo de elementos PropertyInfo. En la línea 14, usamos el método GetType de Type al que le pasamos el nombre de clase completamente calificado -"System.Type"-, e invocamos el método GetProperties sobre la representación obtenida:

propiedades = Type.GetType("System.Type").GetProperties();

> Prueba de ejecución.

Resultado:
Prueba ejecución de uso de método GetProperties
Figura 2. Prueba ejecución de uso de método GetProperties.

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

Este ejemplo conjuga los conocimiento adquiridos en la sección 3.

Compilación:


  1. csc /target.exe ObtencionMiembrosConReflection.cs

Ejecución:


  1. .\ObtencionMiembrosConReflection.exe

Resultado:
Prueba de reflection con Type
Figura 3. Prueba de reflection con Type.

5. Conclusiones

Hemos comprendido el método de descubrimiento de los miembros de un tipo a través de la maquinaria programática de la que dispone la clase System.Type. Varios de sus métodos permiten obtener los constructores, métodos, propiedades, eventos, o cualquier miembro de un tipo. En la siguiente receta, aprenderemos cómo invocar un miembro de un tipo usando reflection.

6. Glosario

  • GetMembers
  • Reflection
  • Representación Type
  • Tipo
  • 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]: C# Typeof Operator - http://www.dotnetperls.com/typeof
[3]: Type.GetMembers Method (System) - http://msdn.microsoft.com/en-us/library/system.type.getmembers(v=vs.110).aspx
[4]: Type.GetMembers Method (System) - http://msdn.microsoft.com/en-us/library/424c79hc(v=vs.110).aspx
[5]: MemberInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo(v=vs.110).aspx
[6]: PropertyInfo.MemberType Property (System.Reflection) - PropertyInfo.MemberType Property (System.Reflection)
[7]: MemberTypes Enumeration (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.membertypes(v=vs.110).aspx
[8]: Type.GetConstructors Method (System) - http://msdn.microsoft.com/en-us/library/System.Type.GetConstructors(v=vs.110).aspx
[9]: Type.GetConstructors Method (System) - http://msdn.microsoft.com/en-us/library/e687hf0d(v=vs.110).aspx
[10]: Type.GetMethods Method (System) - http://msdn.microsoft.com/en-us/library/system.type.getmethods(v=vs.110).aspx
[11]: Type.GetMethods Method (System) - http://msdn.microsoft.com/en-us/library/td205ybf(v=vs.110).aspx
[12]: MethodInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo(v=vs.110).aspx
[13]:MethodInfo Class (System.Reflection) - http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo(v=vs.110).aspx
[14]: Type.GetProperties Method (System) - http://msdn.microsoft.com/en-us/library/System.Type.GetProperties(v=vs.110).aspx


M

No hay comentarios:

Publicar un comentario

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