1

我有包含自我参考的项目列表。例如:
型号

public class Stock{
  public int StockId { get; set; }
  public int? ParentStockId { get; set; }
  public int Level { get; set; }
  public string Name { get; set; }
}

视图模型

public class StockViewModel {
  public int Level { get; set; }
  public string Name { get; set; }
  public IEnumerable<StockViewModel> SubStock { get; set; }
}

样本数据

var stocks = new List<Stock> {
    new Stock{ StockId = 1, Level = 10, Name = "Root1" },
    new Stock{ StockId = 2, Level = 10, Name = "Root2" },
    new Stock{ StockId = 3, ParentStockId = 1, Level = 20, Name = "Area1" },
    new Stock{ StockId = 4, ParentStockId = 2, Level = 20, Name = "Area2" },
    new Stock{ StockId = 5, ParentStockId = 3, Level = 30, Name = "Box11" },
    new Stock{ StockId = 6, ParentStockId = 3, Level = 30, Name = "Box12" },
    new Stock{ StockId = 7, ParentStockId = 4, Level = 30, Name = "Box21" }
};

我使用类似的代码来达到预期的效果。但我确定这是错的。我必须在每个新请求之前进行配置。

        var mapper = new Mapper(); 
        TypeAdapterConfig<Stock, StockViewModel>
            .NewConfig()
            .Map(dst => dst.SubStock, src => stocks.Where(x => x.ParentStockId == src.StockId).ToList());
        var viewStocks = mapper.Map<IEnumerable<Stock>, IEnumerable<StockViewModel>>(stocks.Where(x => x.ParentStockId == null));
        // Sample output
        foreach (var stock in viewStocks){
            Console.WriteLine(stock.Level.ToString() + " " + stock.Name);
            if (stock.SubStock != null) 
                foreach (var stock1 in stock.SubStock){
                    Console.WriteLine("  " + stock1.Level.ToString() + " " + stock1.Name);
                    if (stock1.SubStock != null) 
                        foreach (var stock2 in stock1.SubStock){
                            Console.WriteLine("    " + stock2.Level.ToString() + " " + stock2.Name);
                        }
                }
        }

小提琴
如何映射viewStocks分层?如同

10 Root1
  20 Area1
    30 Box11
    30 Box12
10 Root2
  20 Area2
    30 Box21
4

2 回答 2

1

为了正确分离配置和映射,我传递了一个参数stocks

var viewStocks = stocks.Where(x => x.ParentStockId == null)
            .BuildAdapter()
            .AddParameters("paramKey", stocks)
            .AdaptToType<List<StockViewModel>>();

和我的配置

TypeAdapterConfig<Stock, StockViewModel>
            .NewConfig()
            .Map(dst => dst.SubStock, 
                 src => ((IEnumerable<Stock>)MapContext.Current.Parameters["paramKey"])
                 .Where(x => x.ParentStockId == src.StockId)
                 .BuildAdapter()
                 .AddParameters("paramKey", MapContext.Current.Parameters["paramKey"])
                 .AdaptToType<List<StockViewModel>>());

完整的例子

现在在我的配置中我不需要知道stocks

于 2020-06-17T12:43:26.773 回答
1

您不需要Mapster为每个新请求配置配置。根据https://github.com/MapsterMapper/Mapster/wiki/Config-location

配置应该只设置一次并重新用于映射。因此,我们不应该将配置和映射保持在同一个位置。配置应该保持在入口点,例如Mainfunction 或Global.asax.csor Startup.cs

这样您就可以将该映射移动到入口点:

TypeAdapterConfig<Stock, StockViewModel>
    .NewConfig()
    .Map(dst => dst.SubStock, src => stocks.Where(x => x.ParentStockId == src.StockId).ToList());

此外,为了分离您的配置和映射实例而不是这个

 var viewStocks = mapper.Map<IEnumerable<Stock>, IEnumerable<StockViewModel>>(stocks.Where(x => x.ParentStockId == null));

我更喜欢Adapt如下使用:

var socksWithoutParent = stocks.Where(x => x.ParentStockId == null);
var viewStocks = socksWithoutParent.Adapt<List<StockViewModel>>();

完整示例Fiddle,它将为您提供相同的输出:

10 Root1
  20 Area1
    30 Box11
    30 Box12
10 Root2
  20 Area2
    30 Box21
于 2020-06-12T07:54:10.570 回答