【问题标题】:AutoMapper - Map collections of different types to collection of another type with nestingAutoMapper - 使用嵌套将不同类型的集合映射到另一种类型的集合
【发布时间】:2022-11-14 08:54:01
【问题描述】:

我目前正在努力使用 AutoMapper 版本 10.1.1 配置。 我有以下类型:

class Response
{
    List<Assignment> Assignments { get; }
    List<Product> Products { get; }
}

class Assignment
{
    int AssignmentId { get; set; }
    int ProductId { get; set; } // references Product.ProductId
}

class Product
{
    int ProductId { get; set; }
}

class AssignmentModel
{
    int AssignmentId { get; set; }
    int ProductId { get; set; }
    Product Product { get; set; }
}

对于响应对象的“Assignments”属性中的每个项目,我想根据产品 ID 获取一个具有相应产品的新 AssignmentModel。

当前的解决方案通过将Assignments 映射到新的AssignmentModels 并将Products 映射到现有的AssignmentModels 来工作。缺点是,我必须调用映射器两次。

cfg.CreateMap<Assignment, AssignmentModel>();
cfg.CreateMap<Product, AssignmentModel>()
    .ForMember(
        d => d.Product, opt => opt.MapFrom(s => s))
    .EqualityComparison((s, d) => s.ProductId == d.ProductId)
    .ForAllOtherMembers(opt => opt.Ignore());

var assignments = mapper.Map<ICollection<AssignmentModel>>(response.Assignments);
mapper.Map(response.Products, assignments); // not using the result because it does not return assignments without products
return assignments;

是否有可能在一个电话中做到这一点?像这样:

return mapper.Map<ICollection<AssignmentModel>>(response);

【问题讨论】:

    标签: c# collections merge nested automapper


    【解决方案1】:

    建议在您的场景中使用Custom Type Resolver

    映射配置/配置文件

    cfg.CreateMap<Assignment, AssignmentModel>();
                
    cfg.CreateMap<Response, ICollection<AssignmentModel>>()
        .ConvertUsing<ResponseAssignmentModelCollectionConverter>();
    

    在自定义类型转换器中:

    1. source.Assignments 映射到 List&lt;AssignmentModel&gt;
    2. 使用 LINQ .Join() 将结果从1source.ProductsProductId
      public class ResponseAssignmentModelCollectionConverter : ITypeConverter<Response, ICollection<AssignmentModel>>
      {
          public ICollection<AssignmentModel> Convert(Response source, ICollection<AssignmentModel> destination, ResolutionContext context)
          {
              var _mapper = context.Mapper;
      
              var result = _mapper.Map<List<AssignmentModel>>(source.Assignments);
              result = result.Join(source.Products, 
              a => a.ProductId, 
              b => b.ProductId, 
              (a, b) =>
              {
                  a.Product = b;
                  return a;
              })
              .ToList();
      
              return result;
          }
      }
      
      mapper.Map<ICollection<AssignmentModel>>(response);
      

      Sample Demo on .NET Fiddle

    【讨论】:

    • 谢谢你的反馈!你能想出一种方法来使用基本的自动映射器配置来做到这一点,例如没有转换使用?恕我直言,这会将双映射器调用移动到转换器,从而将第二个映射器调用替换为连接。
    • 嗨,在我看来,除了ConvertUsing 之外,我没有想到任何解决方案。将response.Assignments映射到List&lt;AssignmentModel&gt;后,执行加入assignmentModelListresponse.Products的实现,这部分实际上可以不需要AutoMapper。只是这个转换器将逻辑/实现包装到一个类中,然后您可以使用 AutoMapper 重用,而不是在不同的(调用者)位置编写相同的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多