AutoMapper 展平嵌套集合

11

我试图弄清如何将包含多个订单集合的商家集合展平为一个订单视图模型的列表。

这是我的数据传输对象:

public class Merchant
{
    public string MerchantName { get; set; }
    public List<Order> Orders { get; set; }
}

public class Order
{
    public string OrderId { get; set; }
}

以下是视图模型:

public class OrderViewModel
{
    public string MerchantName { get; set; }
    public string OrderId { get; set; }
}

我的目标是将一个List<Merchant>扁平化为一个List<OrderViewModel>,测试结构应该产生6个视图模型:

var myMerchants = new List<Merchant>
{
    new Merchant
    {
        MerchantName = "Merchant X",
        Orders = new List<Order>
        {
             new Order { OrderId = "Order 1"},
             new Order { OrderId = "Order 2"},
             new Order { OrderId = "Order 3"}
        }
    },
    new Merchant
    {
        MerchantName = "Merchant Y",
        Orders = new List<Order>
        {
            new Order { OrderId = "Order 4"},
            new Order { OrderId = "Order 5"},
            new Order { OrderId = "Order 6"}
        }
    }
 };

 var models = Mapper.Map<List<OrderViewModel>>(myMerchants);
5个回答

10
由于根对象的基数不是1:1(即2个根Merchants需要映射到6个OrderViewModels),您可能需要使用自定义TypeConverter并在集合级别上操作,这样您就可以使用.SelectMany来进行展平:
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();
    }
}

然后您可以引导它:

Mapper.CreateMap<IEnumerable<Merchant>, List<OrderViewModel>>()
    .ConvertUsing<MyTypeConverter>();

然后将其映射为以下内容:
var models = Mapper.Map<List<OrderViewModel>>(myMerchants);

4
有趣的发现是,只需执行以下操作即可实现目标,无需使用automapper。
var models = myMerchants.SelectMany(s => s.Orders.Select(o => new OrderViewModel { MerchantName = s.MerchantName, OrderId = o.OrderId })).ToList();

1

虽然这个问题比较老,但我认为对新版本仍有帮助。

我正在使用自动映射的 .Net Core 2。我更喜欢使用可查询的 ProjectTo 扩展。

queryable
   .SelectMany(outterClass => outterClass.innerList)
   .AsQueryable()
   .ProjectTo<OutterClassDto>();

然后,进行如下配置:
config.CreateMap<OuterClass, OuterClassDto>();

0

同时,也可以将SelectMany与AutoMapper结合使用,并对扁平化集合中的每个项目进行映射。您需要两个映射:Merchant -> OrderViewModel和Order -> OrderViewModel。

var models = myMerchants.SelectMany(s => s.Orders.Select(o => 
{
    var mappedItem = Mapper.Map<OrderViewModel>(s);
    Mapper.Map(o, mappedItem);
    return mappedItem;
})).ToList();

0
Automapper ConvertUsing() 还可以接受一个 Func。
 CreateMap<IEnumerable<Merchant>, IEnumerable<OrderViewModel>>()
     .ConvertUsing((src, desc) => src.SelectMany(m => m.Orders,
     (m, o) => new OrderViewModel
     {
         m.MerchantName,
         o.OrderId
         
     }).ToList());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接