AutoMapper mapping objects in source child list to

2019-05-11 18:36发布

问题:

I have the following situation:

public class Parent : EntityObject
{
    EntityCollection<Child> Children { get; set; }
}

public class Child : EntityObject
{
    int Id { get; set; }
    string Value1 { get; set; }
    string Value2 { get; set; }
}

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

public class ChildViewModel
{
    int Id { get; set; }
    string Value1 { get; set; }
    string Value2 { get; set; }
}

Mapper.CreateMap<ParentViewModel, Parent>();

Mapper.CreateMap<ChildViewModel, Child>();

Is it possible to get AutoMapper to:

  • Map objects in the ParentViewModel.Children list to objects in the Parent.Children EntityCollection with matching Ids.
  • Create new objects in Parent.Children for objects in ParentViewModel.Children where an object with the id from source is not found in the destination list.
  • Remove objects from Parent.Children where the destination id does not exist in the source list.

Am I going about this all wrong?

回答1:

I'm afraid automapper is not meant to be used for mapping to a populated object, it will erase the Parent.Children wen you invoke Map(). You have several approaches here:

  • One is to create yourself the condition to execute the map on childrens:

    foreach (var childviewmodel in parentviewmodel.Children)
    {
        if (!parent.Children.Select(c => c.Id).Contains(childviewmodel.Id))
        {
            parent.Children.Add(Mapper.Map<Child>(childviewmodel));
        }
    }
    

    Other ifs for other behaviour

  • One is to create an IMappingAction and hook it in the BeforeMap method:

    class PreventOverridingOnSameIds : IMappingAction<ParentViewModel, Parent>
    {
        public void Process (ParentViewModel source, Parent destination)
        {
            var matching_ids = source.Children.Select(c => c.Id).Intersect(destination.Children.Select(d => d.Id));
            foreach (var id in matching_ids)
            {
                source.Children = source.Children.Where(c => c.Id != id).ToList();
            }
        }
    }
    

    ..and later on

    Mapper.CreateMap<ParentViewModel, Parent>()
        .BeforeMap<PreventOverridingOnSameIds>();
    

    this way you let automapper do the job.