简体   繁体   中英

Nested mapping using automapper for collection of object

my objects structures are

Class cls1
{
    id,
    name,
    List<Address> address
}

Class cls2
{
    prop1,
    prop2,
    street,
    HouseNumber
}

I want to map cls1 to cls2 where cls2.street should map with street property of Address object.

when i'm trying to Mapper.CreateMap<cls1, cls2>().ForMember(gn => gn.Street, item => item.MapFrom(i => i.address. ...) it is show as a collection. how to resolve this mapping using Automapper

Each instance of cls2 represents an address, plus some other information. Each instance of cls1 has a collection of address. So it will not be possible to map directly from cls1 to cls2, unless you assume there is only one address in each instance of cls1.

To overcome this, map a single cls1 to multiple cls2 by introducing a denormalised object that represents an address plus its parent cls1. The mapping can then be from the denormalised representation to cls2.

public class Cls1AndAddress
{
    public Cls1 Cls1;
    public Address Address;
}

[Test]
public void DenormalizationApproach()
{
    AutoMapper.Mapper.CreateMap<Cls1AndAddress, Cls2>()
        .ForMember(dest => dest.Prop1, opt => opt.MapFrom(src => src.Cls1.Name))
        .ForMember(dest => dest.Street, opt => opt.MapFrom(src => src.Address.Street))
        .ForMember(dest => dest.HouseNumber, opt => opt.MapFrom(src => src.Address.HouseNumber))
        ;

    var c1 = new Cls1
    {
        Addresses = new List<Address>
        {
            new Address {Street = "foo", HouseNumber = 1},
            new Address {Street = "bar", HouseNumber = 2},
        }
    };

    var denormalized = c1.Addresses.Select(address => new Cls1AndAddress {Cls1 = c1, Address = address});

    var c2 = AutoMapper.Mapper.Map<IEnumerable<Cls1AndAddress>, IEnumerable<Cls2>>(denormalized);

    var c2Array = c2.ToArray();
    Assert.AreEqual(2, c2Array.Length);
    Assert.AreEqual("foo", c2Array[0].Street);
    Assert.AreEqual("bar", c2Array[1].Street);
}

On the other hand, if there is only one address per cls1, you could use the more direct route of assuming this in your mapping:

[Test]
public void AssumeSingleApproach()
{
    AutoMapper.Mapper.CreateMap<Cls1, Cls2>()
        .ForMember(dest => dest.Street, opt => opt.MapFrom(src => src.Addresses.Single().Street))
        .ForMember(dest => dest.HouseNumber, opt => opt.MapFrom(src => src.Addresses.Single().HouseNumber))
        ;

    var c1 = new Cls1
    {
        Addresses = new List<Address>
        {
            new Address {Street = "foo", HouseNumber = 1},
            // new Address {Street = "bar", HouseNumber = 2}, This would cause failure
        }
    };

    var c2 = AutoMapper.Mapper.Map<Cls1, Cls2>(c1);

    Assert.AreEqual(c2.Street, "foo");
}

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