2011-11-08 12 views
16

To nie jest tak wiele pytanie, ponieważ znalazłem sposób, aby zrobić to, co chcę, ale wydaje się, że powinien być lepszy sposób to zrobić. Szukałem wszędzie i niczego nie znalazłem.Mapowanie readonly kolekcji dzieci z AutoMapper

Zasadniczo mam to, co uważam za bardzo standardowy model obiektowy.

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

i

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

(ja pominięty właściwości znaczenia dla kontroli problemów i błędów i ochronę dla jasności ...)

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

i

public class ChildDTO 
{ 
} 

Powodem, dla którego używam metody dodawania dzieci do kolekcji, jest zachowanie kontroli nad logiką biznesową, która musi zostać przetworzona po dodaniu dziecka.

Przy standardowej mapowania:

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

Wydaje się działać prawidłowo pochodzące z warstwy usług. Obiekty potomne obiektu domeny doskonale odwzorowują listę instancji ChildDTO.

Jednak odwzorowując odwrotnie, kolekcja w modelu domeny nie jest ustawiona - ponieważ jest to oczywiście tylko do odczytu. Wygląda na to, że nie ma sposobu bezpośredniego ustawienia pola prywatnego za pomocą AutoMappera. Próbowałem różnych sugestii tutaj i innych części internetu.

W końcu wpadłem na następujący mapowania:

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

To działa jak potrzeba. Jednak nie mogę oprzeć się wrażeniu, że musi istnieć lepszy sposób, i nie testowałem tego z istniejącym rodzicem, który miał dzieci zmodyfikowane, a może dodane i usunięte, więc wiem, że to jeszcze nie jest poprawne. Ostatecznie ten model domeny jest utrzymywany przy użyciu NHibernate, więc muszę się tym martwić. Ale jedna rzecz na raz. :)

Mam nadzieję, że może to pomóc komuś, kto napotkał ten sam problem, a być może ktoś, kto rozwiązał go poprawnie, będzie mógł mnie poprawić.

+2

+1 Twoje rozwiązanie map drogowych mnie zapisało. –

+0

Fajne rozwiązanie. Pożyczę to :-) – LeftyX

+0

Świetny pomysł z AfterMap. O wiele łatwiej jest pracować z obiektami Source i Destination niż z ResolutionResult i tym podobnymi! – Andrei

Odpowiedz

0

Myślę, że jeśli zamierzasz chronić właściwości z dobrych powodów logiki biznesowej, byłoby źle, gdyby AutoMapper ominął je podczas wykonywania mapowania. W takich sytuacjach wolę zrezygnować składnię płynnie i umieść logikę tworzenia własnej metody tak:

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

, a następnie:

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

Uważam to łatwiejsze do naśladowania niż o wiele ignoruj ​​deklaracje.

Powiązane problemy