Anthony Sherratt
Anthony Sherratt

Reputation: 475

Automapper - how to map two complex collections to one destination collection object

I have the two distinct objects and would like to map them to one destination object. The source objects are complex objects which contain multiple child objects which would also need to be mapped. I've tried something similar to the below example but as expected, the last mapping will overwrite any previous mapping.

CreateMap<sourceObject, destinationObject>()
.ForMember(d => d.Addresses, o => o.MapFrom(s => s.Addresses.MainAddresses))
.ForMember(d => d.Addresses, o => o.MapFrom(s => s.Addresses.SomeOtherAddresses))

I suppose I'm looking for something like a MapFrom().AndThenMapFrom() method (a join or union type transformation).

I have used a custom value resolver to get around the issue but this seems to defeat the purpose of automapper in my eyes. Any other suggestions would be welcomed.

Upvotes: 2

Views: 1603

Answers (1)

witalego
witalego

Reputation: 561

If you want to concatenate in Addresses results of mappings (MainAddresses to Addresses and SomeOtherAddresses to Addresses), one solution would be

CreateMap<sourceObject, destinationObject>()
    .ForMember(
        d => d.Addresses,
        o => o.MapFrom(
            s => s.Addresses.MainAddresses
                .Cast<object>()
                .Concat(s.Addresses.SomeOtherAddresses)))

or

CreateMap<sourceObject, destinationObject>()
    .ForMember(
        d => d.Addresses,
        o => o.MapFrom(
            s => s.Addresses.MainAddresses
                .Cast<IAddress>()
                .Concat(s.Addresses.SomeOtherAddresses)))

if objects in MainAddresses and SomeOtherAddresses realize IAddress interface.

Another solution is to do it in Before/AfterMap method

CreateMap<sourceObject, destinationObject>()
    .BeforeMap(
        (s, d, c) =>
        {
            var mainAddresses = c.Mapper.Map<IEnumerable<Address>>(s.Addresses.MainAddresses);
            var someOtherAddresses = c.Mapper.Map<IEnumerable<Address>>(s.Addresses.SomeOtherAddresses);

            d.Addresses = mainAddresses
                .Concat(someOtherAddresses)
                .ToArray();
        })
        .ForMember(d => d.Addresses, o => o.Ignore());

In this case mapping for Addresses should be ignored, because we do it "manually" in BeforeMap. Unfortunately both solutions are not elegant as most of simple automapper rules.

Upvotes: 4

Related Questions