Подтвердить что ты не робот

Отображение только детской коллекции с помощью AutoMapper

Это не столько вопрос, сколько я нашел способ сделать то, что хочу, но, похоже, должен быть лучший способ сделать это. Я искал везде и ничего не нашел.

В принципе, у меня есть то, что я считаю очень стандартной объектной моделью.

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

и

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

(Я пропустил свойства, не относящиеся к проблеме, и проверку ошибок и защиту для ясности...)

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

и

public class ChildDTO
{
}

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

При стандартном отображении:

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

Кажется, что он отлично работает с уровня сервиса. Дети объектной карты домена прекрасно соответствуют списку экземпляров ChildDTO.

Однако при сопоставлении обратного пути сборка на модели домена не задана, потому что она явно, очевидно. Кажется, что нет никакого способа напрямую настроить частное поле с помощью AutoMapper. Я пробовал различные предложения, найденные здесь, и другие части Интернета.

В конце я придумал следующее отображение:

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

Это работает так, как я и требовал. Тем не менее, я не могу не чувствовать, что должен быть лучший способ, и я не тестировал это с существующим родителем, у которого были модифицированы и, возможно, добавлены и удалены дети, поэтому я знаю, что это еще не совсем правильно. В конечном счете, эта модель домена сохраняется с использованием NHibernate, поэтому мне нужно беспокоиться об этом. Но одно дело за раз.:)

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

4b9b3361

Ответ 1

Я думаю, что если вы собираетесь защищать свойства по соображениям хорошей бизнес-логики, тогда было бы плохо, если бы AutoMapper обошел их при выполнении своих сопоставлений. В подобных ситуациях я предпочитаю отказаться от свободного синтаксиса и поместить логику создания в свой собственный метод следующим образом:

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

а затем:

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

Я считаю, что это проще следовать, чем иметь много объявлений с игнорированием.