2011-11-08 10 views
16

No es tanto una pregunta, ya que he encontrado una manera de hacer lo que quiero, pero parece que debería haber una mejor manera de hacerlo. He buscado en todas partes y no he encontrado nada.Asignación de la colección de elementos secundarios de lectura con AutoMapper

Básicamente, tengo lo que considero un modelo de objeto muy estándar.

public class Parent 
{ 
    private readonly IList<Child> _children = new List<Child>(); 
    public IEnumerable<Child> Children { get { return _children; } } 
    public void AddChild(Child child) 
    { 
     child.Parent = this; 
     _children.Add(child); 
    } 
} 

y

public class Child 
{ 
    public Parent Parent { get; set; } 
} 

(he omitido propiedades irrelevantes para el problema y comprobación de errores y guardando en aras de la claridad ...)

public class ParentDTO 
{ 
    List<ChildDTO> Children = new List<ChildDTO>(); 
} 

y

public class ChildDTO 
{ 
} 

La razón por la que estoy utilizando un método para agregar elementos secundarios a la colección es mantener el control de la lógica de negocios que debe procesarse cuando se agrega un elemento secundario.

Con la asignación estándar de:

Mapper.CreateMap<Parent, ParentDTO>(); 
Mapper.CreateMap<ParentDTO, Parent>(); 
Mapper.CreateMap<Child, ChildDTO>(); 
Mapper.CreateMap<ChildDTO, Child>(); 

parece que funciona bien procedente de la capa de servicio. Los elementos secundarios del objeto de dominio se correlacionan perfectamente con la lista de instancias ChildDTO.

Sin embargo, al realizar una asignación inversa, la colección en el modelo de dominio no está configurada, porque es de solo lectura, obviamente. No parece haber ninguna forma de establecer directamente el campo privado usando AutoMapper. He intentado varias sugerencias que se encuentran aquí, y otras partes de internet.

Al final, se me ocurrió la siguiente asignación:

Mapper.CreateMap<ParentDTO, Parent>() 
    .ForMember(m => m.Children, o => o.Ignore()) 
    .AfterMap((s, d) => 
         { 
          foreach(var c in s.Children) 
           d.AddChild(Mapper.Map<ChildDTO, Child>(c)); 
         }); 

Esto funciona como yo requería. Sin embargo, no puedo evitar sentir que tiene que haber una mejor manera, y no he probado esto con un padre existente que haya tenido niños modificados y tal vez agregados y eliminados, así que sé que aún no es correcto. En última instancia, este modelo de dominio persiste utilizando NHibernate, por lo que tengo que preocuparme por eso. Pero, una cosa a la vez. :)

Espero que esto pueda ayudar a alguien más que está teniendo el mismo problema, y ​​tal vez alguien que lo ha resuelto correctamente pueda corregirme.

+2

+1 su solución de mapa posterior me salvó. –

+0

Solución fría. Lo tomaré prestado :-) – LeftyX

+0

Excelente idea con AfterMap. ¡Es mucho más fácil trabajar con objetos Source y Destination que con ResolutionResult y cosas por el estilo! – Andrei

Respuesta

0

Creo que si va a proteger las propiedades por buenas razones de lógica comercial, entonces sería malo si AutoMapper las eludió al hacer su mapeo. En situaciones como esta, prefiero abandonar la sintaxis fluida y colocar la lógica de la creación en su propio método como este:

private Parent MapParentDTOToParent(ParentDTO source) 
{ 
    var parent = new Parent(); 
    // Business logic here 
    return parent 
} 

y luego:

Mapper.CreateMap<ParentDTO, Parent>().ConvertUsing(MapParentDTOToParent); 

Me parece más fácil de seguir que tener mucha ignorar declaraciones

Cuestiones relacionadas