简体   繁体   中英

Automapper: DTO with Array to List

I know the basics of Automapper but I was wondering if it can also do more complex things or if I am forced to do things like that manually. Let me explain it with my current scenario.

OrderStatusDTO

public class OrderStatusDTO
{
    [Required]
    public int[] OrderIds { get; set; }
    [Required]
    public int StatusId { get; set; }
    [MaxLength(50)]
    public string Username { get; set; }
    public string Comment { get; set; }
    [Required]
    public DateTime Date { get; set; }
}

The purpose of this DTO is fairly simple; it creates an order status for multiple orders at the same time.

OrderStatus

public class OrderStatus
{
    [Required]
    public int Id { get; set; }
    [Required]
    public int OrderId { get; set; }
    [Required]
    public int StatusId { get; set; }
    [MaxLength(50)]
    public string Username { get; set; }
    public string Comment { get; set; }
    [Required]
    public DateTime Date { get; set; }
}

This is the database entity. StatusId , Username , Comment and Date will be the same for all of them and there should be as many OrderStatus objects as the size of the OrderStatusDTO.OrderIds array. Each object's OrderId property will match with one of the values of the OrderStatusDTO.OrderIds array.

Is it possible to use Automapper for this, such that I could to something like this as the final result:

_mapper.Map<OrderStatusDTO, List<OrderStatus>>(orderStatusDTO);

Edit :

In a loop, it would look like the following.

List<OrderStatus> orderStatus = new List<OrderStatus>();
for (int i = 0; i < orderStatusDTO.OrderIds.Length; i++) {
    OrderStatus orderStatus = new OrderStatus();
    orderStatus.OrderId = orderStatusDTO.OrderIds[i];
    orderStatus.StatusId = orderStatusDTO.StatusId;
    orderStatus.Username = orderStatusDTO.Username;
    orderStatus.Comment = orderStatusDTO.Comment;
    orderStatus.Date = orderStatusDTO.Date;
    orderStatus.Add(orderStatus);
}

Use ProjectTo method for collections.

List<OrderStatus> orderStatus = orderStatusDTO
    .AsQueryable()
    .ProjectTo<OrderStatus>()
    .ToList();

Source:automapper.org

You have to provide automapper configuration like this -

cfg.CreateMap<OrderStatusDTO, List<OrderStatus>>()
                    .ConvertUsing<OrderStatusDTOConverter>();

Where, OrderStatusDTOConverter is defined as -

    public class OrderStatusDTOConverter : ITypeConverter<OrderStatusDTO, List<OrderStatus>>
    {
        public List<OrderStatus> Convert(OrderStatusDTO source, List<OrderStatus> destination, ResolutionContext context)
        {
            var list = new List<OrderStatus>();
            foreach (var orderId in source.OrderIds)
            {
                list.Add(new OrderStatus
                {
                    Comment = source.Comment,
                    Date = source.Date,
                    OrderId = orderId,
                    StatusId = source.StatusId,
                    Username = source.Username
                });
            }
            return list;
        }
    }

Now Map as -

var orderList = mapper.Map<List<OrderStatus>>(orderDTO);

And if you want reverse as well, Add configuration as -

cfg.CreateMap<List<OrderStatus>, OrderStatusDTO>()
                .ForMember(p => p.OrderIds, opts => opts.MapFrom(s => s.Select(r => r.OrderId).ToArray()))
                .ForMember(p => p.StatusId, opts => opts.MapFrom(s => s.Any() ? s.FirstOrDefault().StatusId : 0))
                .ForMember(p => p.Username, opts => opts.MapFrom(s => s.Any() ? s.FirstOrDefault().Username : string.Empty))
                .ForMember(p => p.Date, opts => opts.MapFrom(s => s.Any() ? s.FirstOrDefault().Date : new DateTime()))
                .ForMember(p => p.Comment, opts => opts.MapFrom(s => s.Any() ? s.FirstOrDefault().Username : string.Empty));

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