3

When I map an object with a List property Automapper by default sets the list property on the destination object to the instance from the source object.

Is there a way for automapper to create a new list and copy the items but not copy the list instance?

I would like the following test to pass:

var widget = new Widget
                {
                    Tags = new List<string> {"big", "bright"}
                };

Mapper.Reset();
Mapper.CreateMap<Widget, Widget>();

var widgetCopy = Mapper.Map<Widget, Widget>(widget);

CollectionAssert.Contains(widgetCopy.Tags, "big");
CollectionAssert.Contains(widgetCopy.Tags, "bright");
Assert.AreNotSame(widget.Tags, widgetCopy.Tags);

where the widget class looks like:

class Widget
{
    public IList<string> Tags { get; set; }
}

Currently the last assert fails because the two tags properties point to the same instance of a list. This is a problem when the objects are persisted with NHibernate.

Brownie
  • 7,688
  • 5
  • 27
  • 39

2 Answers2

3

What you're asking for is deep cloning, something AutoMapper isn't really designed to do.

There are other options available. See if ValueInjecter would work for you.

Look at Deep cloning with ValueInjecter

Community
  • 1
  • 1
PatrickSteele
  • 14,489
  • 2
  • 51
  • 54
0

I solve this problem by defining an extension method like this:

public static class DeepCopyExtensions
{
    public static List<T> DeepCopy<T>(this List<T> original)
    {
        lock(original) 
            return original.Select(AutoMapper.Mapper.Map<T, T>).ToList();
    }

    public static T DeepCopy<T>(this T original)
    {
        return AutoMapper.Mapper.Map<T, T>(original);
    }
}

and defining my AutoMapper mapping like this:

Mapper.CreateMap<Widget, Widget>()
    .ForMember(
        dest => dest.Tags,
        opt => opt.MapFrom(src => src.Tags.DeepCopy()));
bikeman868
  • 2,236
  • 23
  • 30