2008-09-06 17 views
10

Me he preguntado acerca de lo apropiado de la reflexión en el código C#. Por ejemplo, he escrito una función que itera a través de las propiedades de un objeto fuente dado y crea una nueva instancia de un tipo especificado, luego copia los valores de las propiedades con el mismo nombre de una a la otra. Creé esto para copiar datos de un objeto LINQ autogenerado a otro con el fin de evitar la falta de herencia de múltiples tablas en LINQ.Justificación para la reflexión en C#

Sin embargo, no puedo evitar pensar que un código como este es realmente 'hacer trampa', es decir, en lugar de utilizar las construcciones de lenguaje proporcionadas para lograr un fin dado, te permite eludirlas.

¿Hasta qué punto es aceptable este tipo de código? ¿Cuáles son los riesgos? ¿Cuáles son los usos legítimos de este enfoque?

Respuesta

1

Puede que sea solo yo, pero la forma en que me gustaría entrar en esto es creando un generador de código: usar la reflexión en tiempo de ejecución es un poco costoso y sin tipear. Crear clases que se generarían de acuerdo con su último código y copiar todo de una manera fuertemente tipada significaría que detectará estos errores en tiempo de compilación.

Por ejemplo, una clase generada puede tener este aspecto:

static class AtoBCopier 
{ 
    public static B Copy(A item) 
    { 
     return new B() { Prop1 = item.Prop1, Prop2 = item.Prop2 }; 
    } 
} 

Si cualquiera clase no tiene las propiedades o cambiar sus tipos, el código no se compilará. Además, hay una gran mejora en los tiempos.

2

Estoy de acuerdo, me da el funciona pero se siente como un hack sentimiento. Intento evitar la reflexión siempre que sea posible. Me han quemado muchas veces después de refactorizar el código que tenía reflejo en él. El código compila bien, las pruebas incluso se ejecutan, pero en circunstancias especiales (que las pruebas no cubrieron) el programa explota en tiempo de ejecución debido a mi refactorización en uno de los objetos en los que se introdujo el código de reflexión.

Ejemplo 1: Reflejando en OR mapper, cambia el nombre o el tipo de la propiedad en su modelo de objeto: Impulsa el tiempo de ejecución.

Ejemplo 2: Estás en una tienda SOA. Los servicios web están completamente desacoplados (o eso crees). Ellos tienen su propio conjunto de clases de proxy generadas, pero en el mapeo que deciden ahorrar algún tiempo y que hacen esto:

ExternalColor c = (ExternalColor)Enum.Parse(typeof(ExternalColor), 
              internalColor.ToString()); 

Debajo de las sábanas Esta es también la reflexión pero hecho por .NET Framework en sí. Ahora, ¿qué ocurre si decide renombrar InternalColor.Grey a InternalColor.Gray? Todo parece estar bien, se construye bien, e incluso funciona bien ... hasta el día en que un usuario estúpido decida usar el color Gris ... en ese punto el mapeador explotará.

8

A veces el uso de la reflexión puede ser un poco complicado, pero muchas veces es simplemente la herramienta de código más fantástica.

Mire la cuadrícula de la propiedad de .Net - cualquiera que haya usado Visual Studio estará familiarizado con ella. Puede apuntar a cualquier objeto y generará un editor de propiedades simple. Eso usa la reflexión, de hecho, la mayoría de las herramientas de VS sí lo hacen.

Mire las pruebas unitarias: se cargan por reflexión (al menos en NUnit y MSTest).

Reflection permite un comportamiento de estilo dinámico a partir de lenguajes estáticos.

La única cosa que realmente necesita es la tipificación de pato - el compilador de C# ya es compatible con esto: se puede foreach nada que se parezca IEnumerable, si se implementa la interfaz o no. Puede usar la sintaxis de la colección C# 3 en cualquier clase que tenga un método llamado Add.

Utilice la reflexión donde sea que necesite un comportamiento de estilo dinámico; por ejemplo, tiene una colección de objetos y desea verificar la misma propiedad en cada uno.

Los riesgos son similares para los tipos dinámicos: las excepciones de tiempo de compilación se vuelven de tiempo de ejecución. Tu código no es tan 'seguro' y tienes que reaccionar en consecuencia.

El código de reflexión .Net es muy rápido, pero no tan rápido como habría sido la llamada explícita.

+0

Si me preguntaran cuáles son los pro y los contras de la reflexión, ¿sería esta una respuesta adecuada? –

1

Recientemente utilicé la reflexión en C# para encontrar implementaciones de una interfaz específica. Había escrito un intérprete simple de estilo por lotes que buscaba "acciones" para cada paso del cálculo en función del nombre de la clase. Reflejando el espacio de nombres actual, aparece la implementación correcta de mi interfaz IStep que puede ejecutarse(). De esta forma, agregar nuevas "acciones" es tan fácil como crear una nueva clase derivada, sin necesidad de agregarlo a un registro, o incluso peor: olvidarse de agregarlo a un registro ...

2

Reflection es una herramienta maravillosa que no podría vivir sin él Puede hacer la programación mucho más fácil y más rápida.

Por ejemplo, utilizo la reflexión en mi capa ORM para poder asignar propiedades con valores de columna de tablas. Si no fuera por la reflexión, he tenido que crear una clase de copia para cada mapeo de tabla/clase.

En cuanto a la excepción de color externo anterior. El problema no es Enum.Parse, sino que el codificador no detectó la excepción adecuada. Como se analiza una cadena, el codificador siempre debe suponer que la cadena puede contener un valor incorrecto.

El mismo problema se aplica a toda la programación avanzada en .Net. "Con un gran poder viene una gran responsabilidad". Usar la reflexión te da mucho poder. Pero asegúrese de saber cómo usarlo correctamente. Hay docenas de ejemplos en la web.

0

Reflection hace que sea muy fácil implementar arquitecturas de plugins donde los plugins DLL se cargan automáticamente en tiempo de ejecución (no vinculados explícitamente en tiempo de compilación).

Se pueden escanear para las clases que implementan/amplían interfaces/clases relevantes. La reflexión se puede usar para crear instancias de estos a pedido.

Cuestiones relacionadas