reflections - Casos de uso para la reflexión
reflection wikipedia (9)
Recientemente, estaba hablando con un compañero de trabajo sobre C ++ y lamenté que no había forma de tomar una cadena con el nombre de un campo de clase y extraer el campo con ese nombre; en otras palabras, carece de reflejo. Me miró desconcertado y preguntó cuándo alguien necesitaría hacer algo así.
Fuera de mi cabeza, no tenía una buena respuesta para él, aparte de "hey, tengo que hacerlo ahora mismo". Entonces me senté y se me ocurrió una lista de algunas de las cosas que realmente hice con la reflexión en varios idiomas. Desafortunadamente, la mayoría de mis ejemplos provienen de mi programación web en Python, y esperaba que la gente de aquí tuviera más ejemplos. Aquí está la lista que surgió:
Dado un archivo de configuración con líneas como
x = "¡Hola mundo!"
y = 5.0
establecer dinámicamente los campos de algún objetoconfig
igual a los valores en ese archivo. (Esto era lo que deseaba poder hacer en C ++, pero en realidad no podía).Al ordenar una lista de objetos, ordene según un atributo arbitrario dado el nombre de ese atributo desde un archivo de configuración o solicitud web.
Al escribir software que utiliza un protocolo de red, la reflexión le permite llamar a métodos basados en valores de cadena de ese protocolo. Por ejemplo, escribí un bot de IRC que traducía
!some_command arg1 arg2
en un método llame aactions.some_command(arg1, arg2)
e imprima la función que devolvió al canal IRC.Cuando uso la función __getattr__ de Python (que es algo así como method_missing en Ruby / Smalltalk) estaba trabajando con una clase con muchas estadísticas, como late_total. Para cada estadística, quería poder agregar _percent para obtener esa estadística como un porcentaje del total de las cosas que estaba contando (por ejemplo, stats.late_total_percent). La reflexión hizo esto muy fácil.
Entonces, ¿alguien aquí puede dar ejemplos de sus propias experiencias de programación de momentos en los que la reflexión ha sido útil? La próxima vez que un compañero de trabajo me pregunte por qué "alguna vez quiero hacer algo así" me gustaría estar más preparado.
Ahora me encuentro en una situación en la que tengo un flujo de XML entrando por el cable y necesito crear una instancia de un objeto Entity que se rellenará de los elementos en la transmisión. Es más fácil usar la reflexión para determinar qué objeto Entity puede manejar qué elemento XML que escribir una instrucción condicional gigantesca de mantenimiento y pesadilla. Claramente hay una dependencia entre el esquema XML y cómo estructurar y nombrar mis objetos, pero controlo ambos, así que no es un gran problema.
Bueno, en los lenguajes de tipo estático, querrá usar el reflejo cada vez que necesite hacer algo "dinámico". Es útil para herramientas (escaneando los miembros de un objeto). En Java se usa bastante en JMX y proxies dinámicos. Y hay toneladas de casos puntuales en los que realmente es la única forma de hacerlo (casi siempre que necesite hacer algo que el compilador no le permitirá).
Considero que la reflexión es muy útil si los datos de entrada (como xml) tienen una estructura compleja que se asigna fácilmente a las instancias de objeto o necesito algún tipo de relación "es una" entre las instancias.
Como la reflexión es relativamente fácil en Java, a veces la utilizo para datos simples (mapas de clave-valor) donde tengo un pequeño conjunto fijo de claves. Por un lado, es fácil determinar si una clave es válida (si la clase tiene un set set setKey (datos de cadena)), por otro lado, puedo cambiar el tipo de datos de entrada (textuales) y ocultar la transformación (por ejemplo, simple int en getKey ()), por lo que el resto de la aplicación puede confiar en los datos escritos correctamente. Si el tipo de algunos pares clave-valor cambia para un objeto (p. Ej., Forma int para flotar), solo tengo que cambiarlo en el objeto de datos y sus usuarios, pero no tengo que tener en cuenta que también debo consultar el analizador . Este podría no ser un enfoque sensato, si el rendimiento es un problema ...
Escribiendo despachadores. Twisted utiliza las capacidades reflexivas de python para despachar llamadas XML-RPC y SOAP. RMI usa la API de reflexión de Java para el envío.
Análisis de línea de comando. Construyendo un objeto de configuración basado en los parámetros de línea de comando que se pasan.
Al escribir pruebas unitarias, puede ser útil utilizar la reflexión, aunque la he usado principalmente para eludir los modificadores de acceso (Java).
Hay muchas veces que desea instanciar dinámicamente y trabajar con objetos donde el tipo no se conoce hasta el tiempo de ejecución. Por ejemplo, con OR-mappers o en una arquitectura de complemento. Los marcos de burla lo utilizan, si desea escribir una biblioteca de registro y dinámicamente desea examinar el tipo y las propiedades de las excepciones.
Si pienso un poco más, probablemente pueda encontrar más ejemplos.
He usado el reflejo en C # cuando había algún método interno o privado en el marco o una biblioteca de terceros a la que quería acceder.
(Descargo de responsabilidad: no es necesariamente una mejor práctica porque los métodos privados e internos pueden cambiarse en versiones posteriores. Pero funcionó para lo que necesitaba).
Puedo enumerar el siguiente uso para la reflexión:
- Enlace tardío
- Seguridad (código de introspección por razones de seguridad)
- Análisis de código
- Tipeo dinámico (el tipado de pato no es posible sin reflexión)
- Metaprogramación
Algunos usos del mundo real de la reflexión de mi experiencia personal:
- Sistema de complemento desarrollado basado en la reflexión
- Modelo de programación orientado a aspectos usado
- Análisis de código estático realizado
- Usó varios marcos de inyección de dependencias
- ...
La reflexión es algo bueno :)
Generalmente utilizo la reflexión para la depuración. La reflexión puede mostrar más fácilmente y con mayor precisión los objetos dentro del sistema que una variedad de declaraciones de impresión. En muchos idiomas que tienen funciones de primera clase, incluso puede invocar las funciones del objeto sin escribir un código especial.
Sin embargo, hay una manera de hacer lo que quiere (ed). Usa una tabla hash. Almacene los campos marcados con el nombre del campo.
Si realmente lo deseaba, podría crear funciones Get / Set estándar o crear macros que lo hagan sobre la marcha. #define GetX() Get("X")
tipo de cosas.
Incluso podría implementar su propia reflexión imperfecta de esa manera.
Para el usuario avanzado, si puede compilar el código, es posible habilitar la generación de resultados de depuración y usar eso para realizar la reflexión.
He usado la reflexión para obtener información actual sobre métodos para excepciones, registro, etc.
string src = MethodInfo.GetCurrentMethod().ToString();
string msg = "Big Mistake";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;
en lugar de
string src = "MyMethod";
string msg = "Big MistakeA";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;
Simplemente es más fácil copiar y pegar herencia y generar código.