Frederik
Frederik

Reputation: 652

AutoMapper - Mapping list of objects to bigger list of objects

Consider the following classes:

public class Colli
{
    public int Count { get; set; }

    public string Description { get; set; }
}

public class Shipment
{
    public List<Colli> Collis { get; set; }
}

public class ShipmentDto
{
    public List<ColliDto> Collis { get; set; }
}

public class ColliDto
{
    public string Description { get; set; }
}

I want the list of Collis to generate a new list of ColliDtos all with the same description based on the Count of a Colli.

Example expected input/output in JSON:

{
    "collis": [
        {
            "count": 2,
            "description": "Colli 1"
        },
        {
            "count": 1,
            "description": "Colli 2"
        }
    ]
}
{
    "collis": [
        {
            "description": "Colli 1"
        },
        {
            "description": "Colli 1"
        },
        {
            "description": "Colli 2"
        }
    ]
}

(The real classes have more fields - this is just a minimal working example)

My research indicates that it should be possible to solve it using an ITypeConverter and I tried creating the following:

public class ColliConverter : ITypeConverter<Colli, List<ColliDto>>
{
    public List<ColliDto> Convert(Colli source, List<ColliDto> destination, ResolutionContext context)
    {
        var retval = new List<ColliDto>();
        for (int i = 0; i < source.Count; i++)
        {
            retval.Add(context.Mapper.Map<ColliDto>(source));
        }
        return retval;
    }
}

With the following mapping profile:

CreateMap<Colli, List<ColliDto>>().ConvertUsing<ColliConverter>();

However, setting a breakpoint in the converter class told me it wasn't being used.

Can this be accomplished with AutoMapper or should I go the 'old route' and do a manual mapping of this class?

Upvotes: 0

Views: 190

Answers (1)

Yong Shun
Yong Shun

Reputation: 51160

Solution 1

  1. Create ShipmentConverter type converter for mapping from the Shipment object to the ShipmentDto object.
public class ShipmentConverter : ITypeConverter<Shipment, ShipmentDto>
{
    public ShipmentDto Convert(Shipment source, ShipmentDto destination, ResolutionContext context)
    {
        destination = new ShipmentDto();
        destination.Collis = new List<ColliDto>();
        
        foreach (var colli in source.Collis)
        {
            for (int i = 0; i < colli.Count; i++)
            {
                destination.Collis.Add(context.Mapper.Map<ColliDto>(colli));
            }
        }
            
        return destination;
    }
}
  1. Mapping profile for Shipment.
CreateMap<Colli, ColliDto>();

CreateMap<Shipment, ShipmentDto>()
    .ConvertUsing<ShipmentConverter>();

Demo Solution 1 @ .NET Fiddle


Solution 2

  1. Create ColliListConverter type converter for mapping from the Colli list to the ColliDto list.
public class ColliListConverter : ITypeConverter<List<Colli>, List<ColliDto>>
{
    public List<ColliDto> Convert(List<Colli> source, List<ColliDto> destination, ResolutionContext context)
    {
        var retval = new List<ColliDto>();
        foreach (var colli in source)
        {
            for (int i = 0; i < colli.Count; i++)
            {
                retval.Add(context.Mapper.Map<ColliDto>(colli));
            }
        }
            
        return retval;
    }
}
  1. Mapping profile for Shipment.
cfg.CreateMap<Colli, ColliDto>();

cfg.CreateMap<List<Colli>, List<ColliDto>>()
    .ConvertUsing<ColliListConverter>();

cfg.CreateMap<Shipment, ShipmentDto>();

Demo Solution 2 @ .NET Fiddle

Upvotes: 1

Related Questions