Search code examples
c#automapper

Automapper: how to map nested object?


I am struggling with the Automapper syntax. I have a List of PropertySurveys, each containing 1 Property. I wish to map each item on the collection into a new object which combines the 2 classes.

So my code looks like;

            var propertySurveys = new List<PropertyToSurveyOutput >();
            foreach (var item in items)
            {
                Mapper.CreateMap<Property, PropertyToSurveyOutput >();
                var property = Mapper.Map<PropertyToSurvey>(item.Property);
                Mapper.CreateMap<PropertySurvey, PropertyToSurveyOutput >();
                property = Mapper.Map<PropertyToSurvey>(item);
                propertySurveys.Add(property);
            }

My simplified classes look like;

public class Property
{
    public string PropertyName { get; set; }
}

public class PropertySurvey
{
    public string PropertySurveyName { get; set; }
    public Property Property { get; set;}
}

public class PropertyToSurveyOutput
{
    public string PropertyName { get; set; }
    public string PropertySurveyName { get; set; }
}

So in the PropertyToSurveyOutput object, after the first mapping PropertyName is set. Then after the second mapping PropertySurveyName is set, but PropertyName is overridden to null. How do I fix this?


Solution

  • First of all, Automapper supports mapping of collections. You don't need to map each item in a loop.

    Second - you don't need to re-create map each time you need to map single object. Put mappings creation to application start code (or before first usage of mapping).

    And last - with Automapper you can create mapping and define how to do custom map for some properties:

    Mapper.CreateMap<PropertySurvey, PropertyToSurveyOutput>()
       .ForMember(pts => pts.PropertyName, opt => opt.MapFrom(ps => ps.Property.PropertyName));
    

    Usage:

    var items = new List<PropertySurvey>
    {
        new PropertySurvey { 
              PropertySurveyName = "Foo", 
              Property = new Property { PropertyName = "X" } },
        new PropertySurvey { 
              PropertySurveyName = "Bar", 
              Property = new Property { PropertyName = "Y" } }
    };
    
    var propertySurveys = Mapper.Map<List<PropertyToSurveyOutput>>(items);
    

    Result:

    [
      {
        "PropertyName": "X",
        "PropertySurveyName": "Foo"
      },
      {
        "PropertyName": "Y",
        "PropertySurveyName": "Bar"
      }
    ]
    

    UPDATE: If your Property class has many properties, you can define two default mappings - one from Property:

    Mapper.CreateMap<Property, PropertyToSurveyOutput>();
    

    And one from PropertySurvey. And use first mapping after you used mapping from PropertySurvey:

    Mapper.CreateMap<PropertySurvey, PropertyToSurveyOutput>()
          .AfterMap((ps, pst) => Mapper.Map(ps.Property, pst));