AutoMapper flatten nested collections
Because the cardinality of the root objects isn't 1:1, (i.e. 2 root Merchants
need to map to 6 OrderViewModels
), you may need to resort to a custom TypeConverter
and operate at the collection level, where you can use .SelectMany
to do the flattening:
public class MyTypeConverter : ITypeConverter<IEnumerable<Merchant>, List<OrderViewModel>>
{
public List<OrderViewModel> Convert(ResolutionContext context)
{
if (context == null || context.IsSourceValueNull)
return null;
var source = context.SourceValue as IEnumerable<Merchant>;
return source
.SelectMany(s => s.Orders
.Select(o => new OrderViewModel
{
MerchantName = s.MerchantName,
OrderId = o.OrderId
}))
.ToList();
}
}
Which you can then bootstrap:
Mapper.CreateMap<IEnumerable<Merchant>, List<OrderViewModel>>()
.ConvertUsing<MyTypeConverter>();
And then mapped as such:
var models = Mapper.Map<List<OrderViewModel>>(myMerchants);
An interesting finding is that, only do the below is enough to achieve the goal without automapper.
var models = myMerchants.SelectMany(s => s.Orders.Select(o => new OrderViewModel { MerchantName = s.MerchantName, OrderId = o.OrderId })).ToList();