简体   繁体   中英

AutoMapper - Map collections of different types to collection of another type with nesting

I am currently struggling with AutoMapper version 10.1.1 config. I have the following types:

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

For every item in the "Assignments" property of the response object, I would like to get a new AssignmentModel with the corresponding product based on the product id.

The current solution works by mapping the Assignments into new AssignmentModels and the Products into the existing AssignmentModels. The downside is, that I have to call the mapper twice.

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;

Is it possible to do that in one call? Like so:

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

Would suggest using Custom Type Resolver for your scenario.

Mapping Configuration / Profile

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

In the Custom Type Converter:

  1. source.Assignments Map to List<AssignmentModel> .
  2. Use LINQ .Join() to join the result from 1 and source.Products by 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM