Due to the fact, that your DTOs could contain different SystemIds and / or UserIds, you'll have to group by this criterion before creating your grouped objects. As always, if needed to wave by hand an instance out from a given instance from another type, the catch all method in AutoMapper is .ConvertUsing() and taking an overload that provides a ResolutionContext to allow calling Map() methods within the method itself.
After giving this theoretical introduction, let's come to some real code that solves your problem:
public static class Program
{
public static void Main(string[] args)
{
var dtos = new[] {
new EventDTO { SystemId = "1", UserId = "10", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
new EventDTO { SystemId = "1", UserId = "20", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
new EventDTO { SystemId = "1", UserId = "30", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
new EventDTO { SystemId = "2", UserId = "10", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
new EventDTO { SystemId = "2", UserId = "20", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
new EventDTO { SystemId = "2", UserId = "30", EventId = $"Event {Guid.NewGuid()}", Message = $"Message {Guid.NewGuid()}" },
};
var config = new MapperConfiguration(conf => conf.AddProfile<EventMappingProfile>());
var mapper = config.CreateMapper();
// Have to ask for list, cause DTOs could differ in SystemId and/or UserId
var logs = mapper.Map<List<EventLog>>(dtos);
// Write result to console
foreach (var log in logs)
foreach (var ev in log.Events)
Console.WriteLine($"{log.SystemId} {log.UserId} {ev.EventId} {ev.Message}");
Console.ReadKey();
}
}
public class EventMappingProfile : Profile
{
public EventMappingProfile()
{
CreateMap<EventDTO, Event>();
CreateMap<IEnumerable<EventDTO>, IEnumerable<EventLog>>()
.ConvertUsing((dtos, _, context) =>
{
return dtos
.GroupBy(dto => (dto.SystemId, dto.UserId))
.Select(group => new EventLog
{
SystemId = group.Key.SystemId,
UserId = group.Key.UserId,
Events = group.Select(context.Mapper.Map<Event>).ToList()
})
.ToList();
});
}
}