Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper: how to map nested object?

Tags:

c#

automapper

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?

like image 756
arame3333 Avatar asked Dec 14 '15 15:12

arame3333


People also ask

Does AutoMapper map nested objects?

With both flattening and nested mappings, we can create a variety of destination shapes to suit whatever our needs may be.

Can AutoMapper map enums?

Alternatively, AutoMapper supports convention based mapping of enum values in a separate package AutoMapper.

Is AutoMapper faster than manual mapping?

Automapper is considerably faster when mapping a List<T> of objects on . NET Core (It's still slower on full . NET Framework).


1 Answers

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));
like image 109
Sergey Berezovskiy Avatar answered Sep 17 '22 14:09

Sergey Berezovskiy