Search code examples
c#arraysautomapperenumerable

AutoMapper collections of strings to object properties in a collection of objects


I'm trying to map an object containing enumerable collections of strings into an object containing an enumerable collection objects whose properties contain the data in those collections.

Consider the following source class:

class Source
{
    public IEnumerable<string> Makes { get; set; }
    public IEnumerable<string> Models { get; set; }
    public IEnumerable<string> Variants { get; set; }
}

And the following destination classes:

class Destination
{
    public IEnumerable<Vehicle> Vehicles { get; set; }
}

class Vehicle
{
    public string Makes { get; set; }
    public string Models { get; set; }
    public string Variants { get; set; }
}

I'd like to map Source into Destination, using the positional location of each Source collection value to map to the properties of a new Vehicle, and add that to the Destination.Vehicles collection. So, if the Source collections each contain 20 items, I would expect the Destination.Vehicles collection to contain 20 Vehicle items.

I've tried the following configuration, but it doesn't resolve out-of-the-box:

    CreateMap<Source, Destination>();
    CreateMap<Source, Vehicle>();

I then went on to try the advice given in this response to a question about flattening nested arrays, but soon became very complex.

Any help would be very appreciated.

Thanks


Solution

  • As mentioned by @madreflection in the comment, you can implement the Custom converter with Enumerable.Zip() to merge those 3 arrays.

    CreateMap<Source, Destination>()
        .ConvertUsing((src, dst) =>
        {
            dst = new Destination();
                        
            dst.Vehicles = src.Makes
                .Zip(src.Models, src.Variants)
                .Select(x => new Vehicle
                {
                    Makes = x.Item1,
                    Models = x.Item2,
                    Variants = x.Item3
                })
                .ToList();
                        
                return dst;
    });
    

    If your .NET Version doesn't support the Enumerable.Zip() with three parameters, then you have to implement to merge the arrays as below:

    int maxElement = new int[] { src.Makes.Count(), src.Models.Count(), src.Variants.Count() }
        .Max();
                        
    var vehicles = new List<Vehicle>();
    for (int i = 0; i < maxElement; i++)
    {
        vehicles.Add(new Vehicle
            {
                Makes = src.Makes.ElementAtOrDefault(i),
                Models = src.Models.ElementAtOrDefault(i),
                Variants = src.Variants.ElementAtOrDefault(i)
            });
    }
    dst.Vehicles = vehicles;