Possible to use AutoMapper to map one object to list of objects?

noocyte picture noocyte · Aug 7, 2013 · Viewed 28k times · Source

These are my classes:

public class EventLog {
        public string SystemId { get; set; }
        public string UserId { get; set; }
        public List<Event> Events { get; set; }
}

public class Event {
        public string EventId { get; set; }
        public string Message { get; set; }
}

public class EventDTO {
        public string SystemId { get; set; }
        public string UserId { get; set; }
        public string EventId { get; set; }
        public string Message { get; set; }
}

Basically I need to go from a single object, with a nested list, to a list of objects with values from the nested list and the parent object. Can this be done in AutoMapper? I realize that I can easily map the Events list and get a list of EventDTO objects and then manually set the SystemId and UserId, it would just be very convenient to let AutoMapper handle it for me.

Answer

Sergey Berezovskiy picture Sergey Berezovskiy · Aug 7, 2013

You will need these three mapings with one custom converter:

Mapper.CreateMap<Event, EventDTO>(); // maps message and event id
Mapper.CreateMap<EventLog, EventDTO>(); // maps system id and user id
Mapper.CreateMap<EventLog, IEnumerable<EventDTO>>()
      .ConvertUsing<EventLogConverter>(); // creates collection of dto

Thus you configured mappings from Event to EventDTO and from EventLog to EventDTO you can use both of them in custom converter:

class EventLogConverter : ITypeConverter<EventLog, IEnumerable<EventDTO>>
{
    public IEnumerable<EventDTO> Convert(ResolutionContext context)
    {
        EventLog log = (EventLog)context.SourceValue;
        foreach (var dto in log.Events.Select(e => Mapper.Map<EventDTO>(e)))
        {
            Mapper.Map(log, dto); // map system id and user id
            yield return dto;
        }
    }
}

Sample code with NBuilder:

var log = new EventLog {
    SystemId = "Skynet",
    UserId = "Lazy",
    Events = Builder<Event>.CreateListOfSize(5).Build().ToList()
};

var events = Mapper.Map<IEnumerable<EventDTO>>(log);