2011-11-08 14 views
16

Non è tanto una domanda, in quanto ho trovato il modo di fare ciò che voglio, ma sembra che ci dovrebbe essere un modo migliore per farlo. Ho cercato ovunque e non ho trovato nulla.Mappatura di raccolte di libri in sola lettura con AutoMapper

Fondamentalmente, ho quello che considero un modello di oggetto molto standard.

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); 
    } 
} 

e

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

(ho omesso proprietà irrilevante per il controllo problema ed errore e guardia per chiarezza ...)

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

e

public class ChildDTO 
{ 
} 

La ragione per cui sto utilizzando un metodo per aggiungere figli alla raccolta è mantenere il controllo della logica aziendale che deve essere elaborata quando viene aggiunto un figlio.

Con la mappatura standard:

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

Sembra funzionare bene proveniente dal livello di servizio. I figli dell'oggetto dominio si associano perfettamente all'elenco delle istanze ChildDTO.

Tuttavia, quando si esegue il mapping in un altro modo, la raccolta sul modello di dominio non è impostata, perché è di sola lettura, ovviamente. Non sembra esserci alcun modo per impostare direttamente il campo privato usando AutoMapper. Ho provato vari suggerimenti trovati qui e in altre parti di Internet.

Alla fine, mi si avvicinò con la seguente mappatura:

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)); 
         }); 

Questo funziona come ho richiesto. Tuttavia, non posso fare a meno di sentire che ci deve essere un modo migliore, e non ho provato questo con un genitore esistente che ha avuto dei bambini modificati e magari aggiunti e rimossi, quindi so che non è ancora corretto. In definitiva, questo modello di dominio è persistente usando NHibernate, quindi devo preoccuparmene. Ma, una cosa alla volta. :)

Speriamo che questo possa aiutare qualcun altro che ha riscontrato lo stesso problema e forse qualcuno che ha risolto correttamente sarà in grado di correggermi.

+2

+1 la soluzione postmap mi ha salvato. –

+0

Soluzione cool. Lo prendo in prestito :-) – LeftyX

+0

Ottima idea con AfterMap. È molto più facile lavorare con oggetti Source e Destination che con ResolutionResult e cose del genere! – Andrei

risposta

0

Penso che se si intende proteggere le proprietà per motivi di buona logica aziendale, sarebbe un problema se AutoMapper le eludesse durante la mappatura. In situazioni come questa preferisco abbandonare la sintassi fluente e posizionare la logica creazione nel proprio metodo come questo:

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

e poi:

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

Trovo questo più facile da seguire che avere un sacco di ignorare le dichiarazioni.