Automapper 将不同类型的集合映射到具有嵌套的另一种类型的集合

Autmapper map collections of different types to collection of another type with nesting

我目前正在为 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 和相应的产品。

当前解决方案的工作原理是将分配映射到新的分配模型,将产品映射到现有的分配模型。缺点是,我必须调用映射器两次。

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);

建议根据您的情况使用 Custom Type Resolver

Mapping Configuration / Profile

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

在自定义类型转换器中:

  1. source.Assignments 映射到 List<AssignmentModel>.
  2. 使用 LINQ .Join()1source.Products 的结果加入 ProductId
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