2012-06-21 13 views
25

Hoy actualicé una aplicación en pleno funcionamiento utilizando AutoMapper v1.1 para usar ahora AutoMapper v2.1 y me encontré con algunos problemas que nunca he encontrado con la versión anterior.AutoMapper utilizando el constructor incorrecto

Aquí es un ejemplo de asignación de código de mi vuelta de Dto a dominio objeto

public class TypeOne 
{ 
    public TypeOne() 
    { 
    } 

    public TypeOne(TypeTwo two) 
    { 
     //throw ex if two is null 
    } 

    public TypeOne(TypeTwo two, TypeThree three) 
    { 
     //throw ex if two or three are null 
    } 

    public TypeTwo Two {get; private set;} 

    public TypeThree Three {get; private set;} 
} 

public class TypeOneDto 
{ 
    public TypeOneDto() 
    { 
    } 

    public TypeTwoDto Two {get; set;} 

    public TypeThreeDto Three {get; set;} 
} 

...

Mapper.CreateMap<TypeThreeDto, TypeThree>(); 
Mapper.CreateMap<TypeTwoDto, TypeTwo>(); 
Mapper.CreateMap<TypeOneDto, TypeOne>(); 

var typeOne = Mapper.Map<TypeOne>(typeOneDto); 

Sin embargo, el primer problema que me encontré con la versión 2.1 fue que AutoMapper estaba tratando de usar el constructor con 2 argumentos cuando uno de los argumentos era nulo y debería estar usando el constructor de 1 arg.

Luego trató de utilizar

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(x => new TypeOne()); 

Pero seguí recibiendo un error 'Invocación ambiguo' que no podía resolver.

Luego probé

Mapper.CreateMap<TypeOneDto, TypeOne>().ConvertUsing(x => new TypeOne()); 

y que se ha creado satisfactoriamente el objeto TypeOne usando el constructor sin parámetros, pero luego no pudieron establecer las propiedades privadas setter.

He buscado ayuda en el sitio web de AutoMapper y he descargado el código fuente para verlo bien pero no he avanzado mucho con la poca documentación sobre y no había muchas pruebas de unidad para ConstructUsing.

¿Hay algo obvio que me falta que debería cambiar con v2.1? Me sorprende que haya cambiado tanto desde v1.1.

+0

posible duplicado de [AutoMapper - cómo asignar a parámetros del constructor en lugar de los emisores de propiedad] (http://stackoverflow.com/questions/2239143/automapper-how-to-map-to-constructor-parameters- set-of-property-setters) –

+0

Sigo recibiendo el mismo error que mencioné anteriormente al usar "ConstructUsing". "Invocación ambigua" cuando creo un nuevo objeto con un constructor sin parámetros. –

Respuesta

48

sólo tiene que añadir explicit cast a

Func<ResolutionContext, TypeOne> 

Aquí está el código:

Mapper.CreateMap<TypeOneDto, TypeOne>().ConstructUsing(
      (Func<ResolutionContext, TypeOne>) (r => new TypeOne())); 

versión actual de AutoMapper funciona como se describe a continuación:

  1. Clasifica tipo de destino de constructores por parámetro cuenta

    destTypeInfo.GetConstructors().OrderByDescending(ci => ci.GetParameters().Length); 
    
  2. Toma el primer constructor cuyos parámetros coinciden con las propiedades de origen (sin ninguna comprobación de valor nulo). En tu caso, es constructor con dos parámetros.

+0

Esto me salvó un poco de dolor. Funciona perfectamente en la versión más reciente de AutoMapper (3.2.1.0) :) ¡Gracias! – Stu1986C

+3

Aunque esta es una publicación bastante antigua, me alegro de haberla encontrado: la secuencia de lo que AutoMapper considera una coincidencia para el constructor parece haber cambiado nuevamente con la versión 4.0.4. Para evitar problemas, podría ser más conservador especificar siempre qué constructor debe usar AutoMapper si tiene más de un constructor. Además, como segunda recomendación, realice una prueba automática que configure todos los mapas y luego llame a 'Mapper.AssertConfigurationIsValid()'. De esta forma, puede anular los problemas desde el principio. Feliz codificación! – Manfred

Cuestiones relacionadas