Reflection (Reflexión)



Documentos relacionados
Partes de un programa en Java. A. Ejemplo de un Programa en Java /* Programa Ejemplo de Java: Muestra una Ventana Archivo: Ejemplo1.

Marco Besteiro y Miguel Rodríguez Introducción al lenguaje C#

Tema 3: Herencia en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

Programación orientada a objetos

Curso de Java POO: Programación orientada a objetos

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

Java Inicial (20 horas)

Programación Orientada a Objetos con Java

Introducción a la programación orientada a objetos

Programación Orientada a Objetos en Java

Ejercicios - Persistencia en Android: ficheros y SQLite

8. Sentencia return y métodos

Prof. Dr. Paul Bustamante

Introducción al lenguaje Java

Contenidos. Gestión dinámica de memoria. Gestión dinámica de memoria. Introducción. 1. Introducción 2. El operador NEW 3. El operador DELETE

JavaScript como Orientación a Objetos

PHP y MySQL. Inicio: - Herencia - Palabra clave Final - Polimorfismo - Type Hinting - Abstracción de clases

Dentro del.net los eventos se utilizan para notificar a nuestros objetos que se ha producido algún tipo de hecho al que nos hemos suscrito.

El lenguaje de programación Java

1. Manejo de memoria estática 2. Manejo de memoria dinámica

Lenguajes de Programación Curso Práctica 4. Herencia. Utilización de interfaces y clases abstractas. 1. Interfaces Clases abstractas 2

Agentes con Interfaz Gráfica.

Patrones para persistencia (I) Ingeniería del Software II

ALGORITMICA Y PROGRAMACION POR OBJETOS I

WEB SERVICES. Manual técnico para desarrollador

Programación Orientada a Objetos en Java

Clases y Objetos. Informática II Ingeniería Electrónica

LENGUAJES DE CONSULTA ORIENTADOS A OBJETOS

Tema: Sobrecarga de Operadores.

Curso de Python Inicial

Objetivos de la práctica: - Practicar uso de ficheros: abrir, cerrar y tratamiento de información contenida en el fichero.

Modulo 1 El lenguaje Java

Modelo de Objetos Distribuidos

Práctica sobre compartición de instancias remotas.

Tema: Clases y Objetos en C++.

Programación Avanzada para Sistemas de Telecomunicación. Objetos y clases. J.C. Cruellas. Objetos y clases

Ejercicios - Persistencia en Android: proveedores de contenidos y SharedPreferences

FICHEROS Y BASES DE DATOS (E44) 3º INGENIERÍA EN INFORMÁTICA. Tema 8. Elementos Básicos

Programación Orientada a Objetos en JAVA

Pruebas de unidad con JUnit

3UiFWLFD. 3URJUDPDFLyQ-DYD

9. Objetos y clases Clases

Administración Local Soluciones

Un elemento de cualquier clase llamada Info; Un puntero a un nuevo nodo llamado sig; De tal forma una unión de nodos hace que tengamos una lista:

El lenguaje C. #define MAX LINEA 1000 /* maximo tamanio de linea de entrada */

Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java

SERVICE ORIENTED ARCHITECTURE (SOA) CONTENIDO

15. Parámetros o argumentos

2.2.- Paradigmas de la POO

EUROPIO ENGINE LAB: FORMULARIOS WEB Y TABLAS HTML EN SOLO

AGRUPA P R OBJET E OS 1

%& %)& '$!%*+ $, %%%&$ %%

Manual de NetBeans y XAMPP

Java: Clases Abstractas e Interfaces

Prácticas de Programación

Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp...

SOLUCION EXAMEN junio 2006

Introducción a la Firma Electrónica en MIDAS

Crear una Nueva Solución Vacía:

Tema 1. Introducción a JAVA

1.1 AUDIENCIA CONTENIDO ITEMS DE MONITOREO ACCIONES MONITOREO Y ALARMA...7. 'HVFULSFLyQ.

Desarrollo de Servicios Web con JBuilder

Introducción a Java LSUB. 15 de enero de 2015 GSYC

Introducción a ZEUS. Introducción. Curso Doctorado Sistemas Multi-agente. Zeus es una herramienta de desarrollo de SMA.

11. Algunas clases estándar de Java (II)

PROGRAMACIÓN ORIENTADA A OBJETOS (L40629) Sabino Miranda-Jiménez

Clase adicional 3. Métodos. Temas

EXAMEN FINAL Metodología y Programación Orientada a Objetos. Curso Cuatrimestre de otoño. 17 de Enero de 2011

Objetos y Clases en Java. ELO 329: Diseño y Programación Orientados a Objetos

Introducción. Herencia y Polimorfismo. Ejemplos (I) Ejemplos (II) Control de Acceso. Herencia

Clases. Java: Clases y Objetos. Clases. Clases. Modificadores de clase. Definición de una clase. Cada objeto es un ejemplar de una clase

GESTIÓN DE REDES PARTE III

Tema: Arreglos de Objetos en C++.

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Conceptos. ELO329: Diseño y Programación Orientados a Objetos. ELO 329: Diseño y Programación Orientados a Objetos

Capítulo 6. Introducción a la POO

Manual de rol gestor de GAV para moodle 2.5

POLIMORFISMO "una interfaz, múltiples métodos".

Programación Avanzada SOLUCIÓN EXAMEN FEBRERO 2011

Manual del Protocolo XML-RPC de Mensajería Negocios

Las propiedades de la clase en java es el equivalente a las variables globales en lenguajes estructurados como el C.

El Concepto De Objeto y Clase

Descripción del tutorial. Contenidos.

Solución al Examen de Prácticas de Programación (Ingeniería Informática)

Introducción a los Tipos Abstractos de Datos

1. Introducción. 1.1 Ejercicio 1: Estación Meteorológica (4.0 pts.) Ejercicio 2: Gestión Académica: Alumnos (5.0 pts.)...

Video 2: Cómo Crear una plantilla para Generar Procedimientos Almacenados

Caso práctico Alquiler de películas en un vídeo-club

CONTENIDO. Programación orientada a objetos - POO. Clases. Constructores y destructores. Definiciones. Entrada y salida

UNIVERSIDAD CATOLICA DE COLOMBIA FACULTAD DE INGENIERIA DE SISTEMAS

Primer Parcial Septiembre 5 de 2009

Tema: Patrones de Diseño.

Para leer la entrada de consola, lo primero que se hace es construir un Scanner que este asociado al flujo de entrada estándar System.

19. Packages o paquetes

Universidad de Cantabria

NOTAS TÉCNICAS SOBRE EL SIT: Comunicados (I)

Libertya Web Service r46gc Índice de contenido

Introducción a la Programación Orientada a Objetos

Introducción a Linux. El regreso a los años 70: la consola (III)

Práctica 5: Common Object Request Broker Architecture CORBA

Transcripción:

Reflection () La reflexión permite obtener información sobre el contenido de un assembly a partir de sus metadatos, en concreto permite: - Obtener información dinámicamente de todos los tipos de un assembly. - Determinar los atributos de los elementos de un assembly y obtener información de éstos. - Cargar dinámicamente y utilizar un assembly (invocar métodos en el assembly, cargar y enlazar dinámicamente tipos para poder utilizarlos). - Generar dinámicamente y ejecutar código intermedio. Los tipos utilizados para la reflexión se encuentran en el namespace System.Reflection. Application Domains La reflexión permite obtener, en tiempo de ejecución, la información sobre el dominio de una aplicación (application domain). Desde el punto de vista de la reflexión, un application domain es la raíz de la jerarquía de tipos y es el contenedor de los assemblies y tipos cuando son cargados en memoria en tiempo de ejecución. En un sentido más físico un application domain es similar a un proceso de Win32, provee un espacio independiente y seguro para el manage code similar al límite de un proceso Win32. El cargador del CLR maneja application domains. La jerarquía de una aplicación en tiempo de ejecución puede verse del siguiente modo (figura 11.1): 1/13

Figura 11.1 La reflexión ofrece objetos que encapsulan el concepto de assembly, el de módulo y el de tipo. Los Assemblies y módulos. Los assemblies son los bloques de construcción de las aplicaciones.net. Son similares a las dll pero en su sentido más amplio (contienen código, recursos, metadatos...): de hecho, se les llama también managed dll. Se podría pensar en un assembly como en un paquete formado por uno o varios ficheros o módulos. Los assemblies son la unidad fundamental de desarrollo, control de versiones, reutilización, control de permisos de seguridad y control de visibilidad de los datos y métodos. Los módulos son los ficheros físicos que componen los assemblies (dll, EXEs, ficheros de recursos...). La clase System.Reflection.Assembly La clase Assembly contiene un gran número de métodos y propiedades que permiten acceder a los metadatos de un assembly, así como cargarlo e incluso ejecutarlo, en caso de que sea ejecutable. Algunos de sus métodos más importantes son: - Load: permite cargar un assembly. Antes de utilizar una instancia de un assembly es necesario cargarlo. Load toma como parámetro el nombre del assembly, lo cual implica que el assembly en ejecución ha de conocer al que se desea cargar, es decir, en tiempo de compilación debe haberse incluido una referencia al assembly a cargar. Por ejemplo: Assembly miassembly = Assembly.Load( AssemblyX ); - LoadFrom: es similar a Load pero toma como parámetro la ruta física del assembly en lugar de su nombre (con lo cual no es necesario que el assembly en ejecución posea una referencia de compilación al assembly a cargar. Por ejemplo: Assembly miassembly = Assembly.LoadFrom( C:\MisProyectos\Reflection\AssemblyX ); - GetModule: Devuelve una instancia del módulo cuyo nombre se le ha de pasar como parámetro. Por ejemplo: Module mimodulo = Assembly.GetModule( ModuloX ); 2/13

- GetModules: Devuelve un array con todos los módulos de un assembly, no recibe parámetros. El siguiente ejemplo muestra como obtener, en ejecución, el modulo principal del assembly, que es el que contiene el manifiesto del assembly: Assembly assemblyppal = Assembly.GetExecutingAssembly(); Module moduloppal = assemblyppal.getmodules()[0]; - GetType: devuelve el objeto Type correspondiente al parámetro pasado. El siguiente ejemplo muestra como crear dinámicamente una instancia de un tipo cargado también dinámicamente: Assembly miassembly = Assembly.Load( AssemblyX ); // obtener un instancia u objeto tipo, el tipo es TipoX Type tipox = miassembly.gettype( TipoX ); //crear una instancia del tipo tipox, //que equivale a crear una instancia de TipoX object o = Activator.CreateInstance(tipox); Un modo más rápido de hacer lo mismo es: Assembly miassembly = Assembly.Load( AssemblyX ); //crear directamente un objeto del tipo TipoX object o = miassembly.createinstance( TipoX ); Es posible cargar un assembly dinámicamente y crear y utilizar instancias de sus tipos de datos (a esto se le llama enlace tardío de tipos y se explicará más adelante). - GetTypes: devuelve un array con todos los tipos de un assembly. Un ejemplo típico de su utilización es: Assembly miassembly = Assembly.Load( AssemblyX ); foreach (Type tipo in miassembly.gettypes()) if (tipo.issubclassof(typeof(tipox)) object o = Activator.CreateInstance(tipo) En este ejemplo, Reflexion_1 carga las dll del Framework.NET mscorlib y System.XML.dll y muestra información básica sobre las mismas. using System.Reflection; class PruebaReflexion1 public static void Main() Assembly as1 = Assembly.Load("mscorlib.dll"); 3/13

//es importante notar el uso de @ para indicar que le sigue //un string de modo que no se interprete \ como carácter //especial. as1 = Assembly.LoadFrom(@"C:\winnt\Microsoft.NET\Framework\v1.0.2 914\System.XML.dll"); El resultado de ejecutar este assembly es: Figura 11.2 Ejemplo: Es posible mostrar información de cualquier assembly independientemente de que pertenezca al framework.net o no. A continuación se muestra un assembly llamado dll_reflexion y se modifica el anterior ejemplo para que cargue y muestre información sobre dll_reflexion. dll_reflexion consta de dos ficheros fuente: CNombre.cs y CNumero.cs. //Fichero CNombre.cs namespace dll_reflexion public class CNombre private string nombre; public CNombre() //desde aquí es posible utilizar nombre. nombre = ""; 4/13

public string Nombre get return nombre; set nombre = value; public void mostrarnombreynumero (int inum) //desde aquí es posible utilizar nombre. System.Console.WriteLine("El valor del nombre es: " + nombre); System.Console.WriteLine("El valor del parámetro es:" + inum); //Fichero CNumero.cs namespace dll_reflexion public class CNumero private int numero; public CNumero() //desde aquí es posible utilizar numero. numero = 0; public int Numero get return numero; set numero = value; public void mostrarnumeroynombre (string snombre) //desde aquí es posible utilizar numero. System.Console.WriteLine("El valor del numero es: " + numero); System.Console.WriteLine("El valor del parámetro es: " + snombre); 5/13

El proyecto Reflexion_1 modificado es: using System.Reflection; class PruebaReflexion1 public static void Main() Assembly as1 = Assembly.Load("mscorlib.dll"); //es importante notar el uso de @ para indicar que le sigue //un string de modo que no se interprete \ como carácter //especial. as1 = Assembly.LoadFrom(@"C:\winnt\Microsoft.NET\Framework\v1.0.2 914\System.XML.dll"); as1 = Assembly.LoadFrom(@"C:\progs\dll_reflexion\obj\debug\dll_re flexion.dll"); El resultado de ejecutarlo es: Figura 11.3 6/13

La clase System.Reflection.Module Al igual que la clase Assembly, la clase Module ofrece un gran número de métodos que permiten obtener información sobre los módulos de un assembly. Un módulo, del mismo modo que un assembly, contiene tipos. Por tanto, la clase Module ofrece los métodos GetType, GetTypes, cuyo funcionamiento es el mismo que en la clase Assembly. Además de estos métodos ofrece otros como el método Assembly, que devuelve el assembly para la instancia del módulo a través de la cual se invoca. Para obtener un módulo a partir de un assembly se pueden utilizar los métodos: - GetModule - GetModules - GetLoadedModules En el siguiente ejemplo se carga el asembly dll_reflexion.dll y, además de mostrar información básica sobre el mismo, se obtiene y se muestra el nombre de todos sus módulos. using System.Reflection; class PruebaReflexion2 public static void Main() Assembly as1 = Assembly.LoadFrom(@"C:\progs\dll_reflexion\obj\debug\dll_re flexion.dll"); Module[] m1 = as1.getmodules(); foreach (Module m in m1) System.Console.WriteLine("Nombre del módulo: " + m.name); El resultado de ejecutar este ejemplo es: 7/13

Figura 11.4 Los Tipos. Los tipos son la base de la reflexión, corresponden a la clase System.Type, que representa los metadatos para la declaración de tipo en una aplicación. La clase System.Reflection.Type Type es una clase base abstracta. Los miembros de esta clase permiten obtener información sobre una declaración de tipo, como por ejemplo los constructores, los métodos, campos, propiedades y eventos de una clase, así como el módulo y el assembly al que pertenece la clase. Existen varios modos de obtener una referencia a un tipo, los más significativos son: - Utilizar el operador typeof. Por ejemplo: Type tipo = typeof (int); - Utilizar el método GetType, que toda clase hereda de System.Object. Ejemplo: int mientero = 5; Tipo tipo = mientero.gettype(); - Utilizar el método static GetType, de la clase Type: Type tipo = Type.GetType( System.Int32 ); 8/13

Una vez se dispone de una referencia a un tipo de datos pueden utilizarse los métodos y propiedades de la clase Type para obtener información sobre el tipo referenciado. Los métodos más relevantes son: - GetConstructor y GetConstructors: devuelven respectivamente una referencia o un array de referencias de tipo ConstructorInfo. ConstructorInfo es un tipo de datos que contiene información sobre el constructor de un Tipo e incluso permite invocarlo (mediante el método Invoke). - GetMethod y GetMethods: devuelven respectivamente una referencia o un array de referencias de tipo MethodInfo (similar a ConstructorInfo pero para métodos). - GetMember y GetMembers: Devuelven respectivamente una referencia o un array de referencias de tipo MemberInfo. Se considera un miembro de un Tipo a las propiedades, métodos, eventos, campos... - Los siguientes métodos se comportan de modo análogo a los anteriores: o GetField y GetFields o GetEvent y GetEvents o GetInterface y GetInterfaces o GetProperty y GetProperties Las propiedades más relevantes son: - Name: devuelve un string que contiene el nombre del tipo de datos. - FullName: devuelve el nombre completo del tipo, incluido el namespace. - Namespace: devuelve el namespace al que pertenece el tipo de datos. - IsClass: devuelve True si el tipo es una clase. - IsValueType: devuelve True si el tipo es valor (recuérdese que los tipos posibles son referencia y valor, existiendo un tercer tipo inseguro que es puntero ) - BaseType: devuelve el tipo base del tipo dado. - UnderlyingSystemType: devuelve el tipo IL del CLR correspondiente al tipo. - Attributes: devuelve los atributos asociados al tipo. - Assembly: devuelve una referencia al assembly al que pertenece el tipo. En el siguiente ejemplo Reflexion3 se carga el assembly dll_reflexion.dll y se muestra información sobre sus tipos. using System.Reflection; class PruebaReflexion3 public static void Main() 9/13

Assembly as1 = Assembly.LoadFrom(@"C:\progs\dll_reflexion\obj\debug\dll_re flexion.dll"); Type[] t1 = as1.gettypes(); foreach (Type t in t1) System.Console.WriteLine("Nombre del tipo: " + t.name); El resultado de ejecutar este ejemplo es: Figura 11.5 Enlace tardío de tipos a una aplicación. El enlace tardío de tipos consiste en que una aplicación cargue, instancie y utilice un tipo en tiempo de ejecución. Una vez obtenida una referencia a un tipo de datos, puede crearse una instancia de tal tipo de datos mediante el método CreateInstance de la clase System.Activator. A continuación se pueden utilizar los métodos de la clase Type (GetMethods, GetMembers...) para obtener los métodos, miembros, etc. del tipo y utilizarlos. Un caso interesante es la clase MethodInfo. GetMethods devuelve un objeto de tal clase, el cual contiene información sobre un método. La clase MethodInfo posee un 10/13

método llamado Invoke, a través del cual se puede invocar el método cuya información posee el objeto MethodInfo devuelto por GetMethods. Ejemplo: using System.Reflection; class PruebaEnlaceTardio public static void Main() Assembly as1 = Assembly.LoadFrom(@"C:\progs\dll_reflexion\obj\debug\dll_re flexion.dll"); Type[] t1 = as1.gettypes(); foreach (Type t in t1) System.Console.WriteLine("Nombre del tipo: " + t.name); if (t.name.equals("cnumero")) //Se crea un objeto de la clase CNumero, que es //el tipo que referencia t object obj = Activator.CreateInstance(t); //Se obtiene el método mostrarnumeroynombre MethodInfo metinf = t.getmethod("mostrarnumeroynombre"); System.Console.WriteLine("Invocación del método mostrarnumeroynombre:"); //MethodInfo posee un método llamado 'Invoke' //mediante 'Invoke' puede invocarse al método //obtenido 'Invoke' recibe 2 parámetros: //1) El objeto al que pertenece el método a //invocar //2) Un array de objetos con los parámetros del //método a invocar object[] arobjs = "Hola"; metinf.invoke(obj, arobjs); El resultado de ejecutar este ejemplo es: 11/13

Figura 11.6 Creación de nuevos tipos en tiempo de ejecución. Es posible definir dinámicamente un assembly, módulos dentro del assembly, tipos en los módulos, con sus miembros, e incluso emitir código IL que implemente la funcionalidad de tales métodos. Para realizar esta labor existen clases como AppDomain, AssemblyBuilder, AssemblyName, ModuleBuilder, TypeBuilder, MethodBuilder, ILGenerator Todas estas clases pertenecen al namespace System.Reflection.Emit. En el siguiente ejemplo se muestra cómo generar dinámicamente un assembly y un módulo, así como un tipo de datos CSaludar con un método Saludar e invocarlo. using System.Reflection; using System.Reflection.Emit; namespace EmisionCodigo public class Emision static void Main() //Obtención del AppDomain actual. AppDomain appd = AppDomain.CurrentDomain; //Creación de un assembly de modo dinámico //en el AppDomain actual. AssemblyName asn = new AssemblyName(); asn.name = "AssemblyDinamico"; AssemblyBuilder asb = appd.definedynamicassembly(asn, AssemblyBuilderAccess.Run); //Creación de un módulo en el Assembly dinámico //Assembly assem = (Assembly) asb; ModuleBuilder modb = asb.definedynamicmodule("modulodinamico"); 12/13

//Creación de un Tipo (CSaludo) y de un método //(Saludar) para tal tipo TypeBuilder typb = modb.definetype("csaludar", TypeAttributes.Public); MethodBuilder metb = typb.definemethod("saludar", MethodAttributes.Public, null, null); //Generación del código IL (MSIL) para el método //Saludar el método GetILGenerator devuelve una //referencia al generador de código asociado a un //método ILGenerator ilg = metb.getilgenerator(); ilg.emitwriteline("hola desde el codigo generado dinámicamente"); ilg.emitwriteline(" "); ilg.emit(opcodes.ret); //Creaación del Tipo typb.createtype(); //Utilización del Tipo object ob = Activator.CreateInstance(typB); typb.getmethod("saludar").invoke(ob, null); El resultado de ejecutar este ejemplo es: Figura 11.7 13/13