AutoMapper - отображение дочерних коллекций в viewmodel - PullRequest
9 голосов
/ 25 ноября 2011

У меня есть модель представления, которая должна отображать определенное поле IEnumerable в виде разделенного точкой с запятой текстового поля. Сначала я думал об использовании DefaultModelBinder для его преобразования, но мне было трудно думать, как добиться этого в обоих направлениях (dto <-> viewmodel).

Псевдонимы - это поле, которое я пытаюсь отобразить как одно текстовое поле, разделенное точкой с запятой.

public class Parent
{
    public IEnumerable<Child> Children { get; set; }
}

public class Child
{
    public IEnumerable<string> Nicknames { get; set; }
}

Поэтому я решил попробовать AutoMapper, я создал две ViewModels:

public class ParentViewModel
{
    public IEnumerable<ChildViewModel> Children { get; set; }
}

public class ChildViewModel
{
    public string Nicknames { get; set; }
}

Затем я создал сопоставления, подобные этому, для детей (для краткости опущено обратное преобразование)

Mapper.CreateMap<Child, ChildViewModel>().ForMember(
d => d.Nicknames, o => o.ResolveUsing<ListToStringConverter>().FromMember(s => s.Nicknames);

Затем для родителя создали наивную карту (опять же, опущено в обратном направлении)

Mapper.CreateMap<Parent, ParentViewModel>();

Я действительно ожидал, что дочерние отображения происходят автоматически, но они этого не делают, я уже создал слишком много «правильного» кода, чтобы решить действительно простую проблему, которая в любой другой более простой / старой среде без MVC, я бы покончим с давным-давно :) Как я могу продолжить и сказать AutoMapper преобразовывать детей без написания другого "распознавателя для детей".

Обдумал ли я это, и есть более простой способ?

Спасибо!

Ответы [ 2 ]

12 голосов
/ 25 ноября 2011

попробуй

Mapper.CreateMap<Parent, ParentViewModel>();
Mapper.CreateMap<Child, ChildViewModel>();

var v = Mapper.Map<Parent, ParentViewModel>(parent);
5 голосов
/ 02 декабря 2014

Нашел это решение https://stackoverflow.com/a/7555977/1586498,, которое работает для меня:

Mapper.CreateMap<ParentDto, Parent>()
  .ForMember(m => m.Children, o => o.Ignore()) // To avoid automapping attempt
  .AfterMap((p,o) => { o.Children = ToISet<ChildDto, Child>(p.Children); });

Функция ToISet определена в приведенной выше ссылке.

Более простые примеры 'просто работают'в LinqPad - поэтому требуется дополнительное расследование.

Полный список работающей программы:

    public class Child{ public string Name  {get; set; }}
    public class ChildDto{  public string NickName {get; set; }}
    public class Parent{    public virtual IEnumerable<Child> Children  {get; set; }}
    public class ParentDto{ public IEnumerable<ChildDto> Kids  {get; set; }}

    private static void Main()
    {
        AutoMapper.Mapper.CreateMap<Parent, ParentDto>().ForMember(d=>d.Kids, opt=>opt.MapFrom(src=>src.Children));
        AutoMapper.Mapper.CreateMap<Child, ChildDto>().ForMember(d=>d.NickName, opt=>opt.MapFrom(src=>src.Name));

        var pList = new HashSet<Parent>{
            new Parent{ Children = new HashSet<Child>{new Child{Name="1"}, new Child{Name="2"}}},
            new Parent{ Children = new HashSet<Child>{new Child{Name="3"}, new Child{Name="4"}}},
        };

        var parentVm = AutoMapper.Mapper.Map<IEnumerable<Parent>, IEnumerable<ParentDto>>(pList);
        parentVm.Dump();    
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...