AutoMapper and flattening nested arrays

Bryan Slatner picture Bryan Slatner · Nov 12, 2012 · Viewed 12.1k times · Source

I'm trying to use AutoMapper to flatten multiple levels of arrays.

Consider the following source classes:

class X {
    public string A { get; set; }
    public Y[] B { get; set; }
}

class Y {
    public string C { get; set; }
    public Z[] D { get; set; }
}

class Z {
    public string E { get; set; }
    public string F { get; set; }
}

And the following destination:

class Destination {
    public string A { get; set; }
    public string C { get; set; }
    public string E { get; set; }
    public string F { get; set; }
}

What I'd like to be able to do is get a List from one or more X, e.g.:

Mapper.Map<IEnumerable<X>, IEnumerable<Destination>>(arrayOfX);

I'm unable to figure out what sort of mapping configuration to use to achieve this. MapFrom seems like the way to go for 1:1 compositions, but doesn't seem to be able to handle the array (or other enumerable) unless I use AutoMapper's destination naming convention.

Any insights on how to achieve this?

Answer

Prasad Kanaparthi picture Prasad Kanaparthi · Nov 12, 2012

Try this mapper,

Mapper.CreateMap<Z, Destination>();
Mapper.CreateMap<Y, Destination>();
Mapper.CreateMap<X, Destination>()
    .ForMember(destination => destination.A, options => options.MapFrom(source => source.A)).IgnoreAllNonExisting()
    .ForMember(destination => destination.C, options => options.MapFrom(source => Mapper.Map<IEnumerable<Y>, IEnumerable<Destination>>(source.B).FirstOrDefault().C))
    .ForMember(destination => destination.E, options => options.MapFrom(source => Mapper.Map<IEnumerable<Z>, IEnumerable<Destination>>(source.B.SelectMany(d => d.D)).FirstOrDefault().E))
    .ForMember(destination => destination.F, options => options.MapFrom(source => Mapper.Map<IEnumerable<Z>, IEnumerable<Destination>>(source.B.SelectMany(d => d.D)).FirstOrDefault().F));

var result = Mapper.Map<IEnumerable<X>, IEnumerable<Destination>>(arrayOfX);