3

I have a problem with Automapper. I set up a test windows form application and below is the code. Also look at the comments after each MessageBox:

public class FirstClass
    {
        public string FirstProp { get; set; }
        public IList<FirstClassChild> Children { get; set; }
    }

    public class FirstClassChild
    {
        public string FirstChildProp { get; set; }
    }

    public class SecondClass
    {
        public string FirstProp { get; set; }
        public string SecondProp { get; set; }
        public IList<SecondClassChild> Children { get; set; }
    }

    public class SecondClassChild
    {
        public string FirstChildProp { get; set; }
        public string SecondChildProp { get; set; }
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            AutoMapper.Mapper.CreateMap<FirstClass, SecondClass>();
            AutoMapper.Mapper.CreateMap<FirstClassChild, SecondClassChild>();

            var f = new FirstClass { FirstProp = "FirstClass" };
            f.Children = new List<FirstClassChild> { new FirstClassChild { FirstChildProp = "FirstClass" } };
            var s = new SecondClass { FirstProp = "SecondClass", SecondProp = "SecondClass" };
            s.Children = new List<SecondClassChild> { new SecondClassChild { FirstChildProp = "SecondClass", SecondChildProp = "SecondClass" } };
            AutoMapper.Mapper.Map(f, s);

            var fc = new FirstClassChild { FirstChildProp = "FirstClass" };
            var sc = new SecondClassChild { FirstChildProp = "SecondClass", SecondChildProp = "SecondClass" };
            AutoMapper.Mapper.Map(fc, sc);

            MessageBox.Show(sc.FirstChildProp);//FirstClass as expected
            MessageBox.Show(sc.SecondChildProp);//SecondClass as expected

            MessageBox.Show(s.FirstProp);//FirstClass as expected
            MessageBox.Show(s.SecondProp);//SecondClass as expected
            MessageBox.Show(s.Children.First().FirstChildProp);//FirstClass as expected
            MessageBox.Show(s.Children.First().SecondChildProp);//Empty not expected!!

        }
    }

What can I do to avoid this? Is this behavior expected? Anyway can anyone guide me how make SecondClass childs SecondChildProp to remain "SecondClass" as it is before the mapping occurs.

John
  • 2,043
  • 5
  • 28
  • 49

1 Answers1

5

I asked a similar question here and found another similar one here.

I think @PatrickSteele makes a very good point: how is AutoMapper supposed to map a source list to a dest list of existing objects, when the dest list may not necessarily bear any resemblance to the source list? i.e. "But what if one list has 3 and the other list has 5?"

If you are sure that FirstClass and SecondClass have the same number of Children, and if the FirstClass's Nth Child always corresponds to SecondClass's Nth child, you could try something like this:

Mapper.CreateMap<FirstClass, SecondClass>()
    .ForMember(m => m.Children, o => o.Ignore())
    .AfterMap((src, dest) =>
        {
            for (var i = 0; i < dest.Children.Count; i++)
                Mapper.Map(src.Children[i], dest.Children[i]);
        });

or if FirstChildProp is some kind of unique key:

Mapper.CreateMap<FirstClass, SecondClass>()
    .ForMember(m => m.Children, o => o.Ignore())
    .AfterMap((src, dest) =>
        {
            foreach (var dChild in dest.Children)
            {
                var sChild = src.Children.Single(c => c.FirstChildProp == dChild.FirstChildProp);
                Mapper.Map(sChild, dChild);
            }
        });
Community
  • 1
  • 1
Merenzo
  • 5,326
  • 4
  • 31
  • 46
  • This make sense, thank you. I didn't recognize the complexity, being blinded by my isolated case I had. – John Jan 10 '13 at 08:04
  • A second thought, about the argumentation that AutoMapper can not possibly know about the children in the list etc. Isn't it a little bit awkward that AutoMapper maps FirstChildProp? Seems inconsistent to me. – John Jan 10 '13 at 08:44
  • 1
    @John - behind the scenes, I don't think Automapper is mapping the FirstChildProp **into** the existing SecondClassChild object. Rather, I expect it is **nuking** SecondClass's `Children` list entirely, and overwriting it with a fresh List of SecondClassChild that it has just created (using `FirstClass.Children` as the mapping source.) This should become more apparent when the source.Children and dest.Children lists have different lengths. – Merenzo Jan 10 '13 at 09:07