2010-08-27 4 views
8

Al atravesar capas, es muy tedioso realizar asignaciones de derecha a izquierda como una manera de completar los modelos. Por ejemplo:Copia de modelos entre capas

employeeViewModel.FirstName = employeeModel.FirstName; 
employeeViewModel.LastName = employeeModel.LastName; 
... 

Por lo tanto, podemos construir una ModelCopier que utiliza la reflexión para copiar modelos:

var employeeViewModel = ModelCopier.Copy<EmployeeViewModel>(employeeModel); 

Esta técnica simplifica enormemente la tarea. Sin embargo, hay algunas cosas que son bastante inquietante sobre esto:

  • Hemos perdido efectivamente la capacidad de rastrear los usos de las propiedades en los objetos de origen y destino. Por ejemplo, encontrar usos (en Resharper) de la propiedad FirstName no revela los casos de ModelCopier.
  • Si cambiamos el nombre de una propiedad en la clase de origen o de destino, podemos causar involuntariamente excepciones de tiempo de ejecución ya que es posible que no nos demos cuenta de que debemos actualizar tanto la clase de origen como la de destino.

En un extremo del espectro, podemos usar el reflejo que es muy fácil, pero a costa de la mantenibilidad. El extremo opuesto del espectro es muy tedioso pero muy fácil de mantener.

Reflexión (Fácil y peligroso) < -----> asignación directa (tedioso y Mantenible)

Tengo curiosidad por si alguien ha encontrado un compromiso que ofrece la facilidad de uso de la reflexión de la copia con la mantenibilidad de la asignación directa.

Una solución que hemos entretenido fue crear un complemento que genere métodos de extensión que manejen la asignación de propiedades para cada caso. En otras palabras, crea una herramienta que manejará la parte tediosa.

EDIT:

Por favor, comprenda que esta cuestión no se trata de qué herramienta de mapeo de usar. Estoy tratando de comprender cómo podemos disfrutar de los beneficios del mapeo basado en la reflexión, al mismo tiempo que disfrutamos de los beneficios de la mantenibilidad proporcionados por la asignación directa (o un contrato de mapeo de propiedad).

Respuesta

3

Probablemente el compilador no haga la prueba necesaria en todo el código ... ahí es donde se realizan las pruebas unitarias. Si ha definido una prueba para la conversión entre las clases en las diferentes capas (sí, todas las conversiones posibles que necesita realizar, de lo contrario, ¿cómo puede estar seguro de que su enfoque de reflexión funcionará en todas las situaciones una vez en producción?), simplemente ejecutar la prueba le dirá al desarrollador que cambió el nombre de la propiedad, que la solución ya no pase todas las pruebas. Debe ejecutar cada prueba (prueba de unidad, no prueba de integración) cada vez que quiera verificar su código fuente ... y eso no debería ser un par de meses de codificación :))

Así que realmente vote por el uso del enfoque de reflexión, picante con un enfoque de prueba de cuchara de unidad.

+0

@themarcuz - Estoy de acuerdo, un conjunto de pruebas unitarias detectaría el problema. Mientras discutíamos el tema, lo mencionamos y el principal detractor fue que depende de que la prueba de la unidad esté funcionando. Tal vez la mejor respuesta es asegurarse de que tengamos pruebas unitarias que prueben explícitamente la operación de mapeo. Todavía estaría bien si pudiéramos detectar el problema en tiempo de compilación. –

+1

@Page Brooks: por definición, el compilador ejecuta el código que ha escrito. Entonces, la única forma de que lo haga es que el cheque que necesita es escribir el código (manualmente o con un complemento VS como lo indicó anteriormente). No hay otra opción: - desea verificar el código en tiempo de compilación -> escribe el código (que es lo que quiere evitar) - desea evitar escribir el código -> pierde la funcionalidad de verificación del compilador (pero usted no quiere esto también) Pero lo que tiene que lograr es evitar que alguna actualización desencadena un error en el tiempo de ejecución: mejorar el comportamiento de prueba de su equipo es la mejor manera, IMHO – themarcuz

+1

Craig Lairman sugest para registrar cada 30 minutos ... pero digamos una hora ... y tienes que ejecutar toda la prueba antes del check-in. Así que no hay mucho espacio para ese tipo de errores. Sé que no es a prueba de mono como lo es el compilador, pero es la mejor solución – themarcuz

10

En serio, use AutoMapper. Le permite configurar conversiones de un tipo a otro tipo. Cualquier cambio en los nombres de propiedades se romperá la configuración de la AutoMapper, que la reflexión no:

Mapper.CreateMap<SiteDto, SiteModel>(); 
Mapper.CreateMap<SiteModel, SiteDto>(); 

continuación para asignar desde y hacia, que acaba de hacer lo siguiente:

SiteDto dto = Mapper.Map<SiteModel, SiteDto>(targetModel); 
SiteModel model = Mapper.Map<SiteDto, SiteModel>(targetDto); 
+2

auto mapper es el camino a seguir con seguridad. ¡es muy bueno! – Patricia

+0

Ya hemos bajado por la ruta de AutoMapper. El problema que hemos encontrado con AutoMapper es que en aplicaciones a gran escala terminas escribiendo muchos mapas de propiedades. No me opongo a tener muchos mapas de propiedades, pero si tuviéramos algo que pudiera ayudar con la creación inicial de los mapas sería mucho más productivo. –

+1

Estas son algunas de las críticas de Automapper. Si sigues un enfoque basado en la convención para nombrar, te ahorrará toneladas de tiempo. Si estás escribiendo toneladas de código de mapeo con Automapper entonces estás haciendo algo mal. Es realmente extraño tener clases "asignables" con nombres de propiedades completamente diferentes. – jfar

0

Una forma sería la de escriba una utilidad por separado que utiliza la reflexión para obtener los nombres de las propiedades del modelo y luego escribe el código fuente para exponer las propiedades.

+0

Hemos considerado este enfoque. Pero nos gustaría evitar tomar una dependencia de una herramienta separada si es posible. Todavía pienso que esta es una opción sin embargo. –

1

Tengo curiosidad por si alguien ha encontrado un compromiso que ofrece la facilidad de utilizando la reflexión de la copia con la capacidad de mantenimiento de la asignación directa.

Parece que está tratando de obtener su pastel y comérselo.

Este es un problema que los lenguajes dinámicos enfrentan a diario. No hay una pastilla magica. Haga las asignaciones izquierda-derecha y obtenga la protección del compilador o ajuste sus asignaciones críticas en pruebas unitarias.

Mi instinto me dice que esto es un problema de diseño, no de código.

+0

¡Estoy intentando ciertamente tener mi torta y comerla! ¿Puede explicar por qué puede ser un problema de diseño? Tal vez estamos haciendo algo que podríamos evitar por completo? ¡Gracias por tu ayuda! –

0

sus requisitos van más allá del tiempo de ejecución (implementación), ya que usted (y todos nosotros) necesitamos gráficos de dependencia, etc. Esto significa que el descubrimiento dinámico con reflejo está fuera. Parece que necesita una solución en tiempo de compilación. Además de la sugerencia de @amaca de un complemento de generación de código (que se puede escribir fácilmente), ¿qué otras opciones podría haber?

Cuestiones relacionadas