C# 使用automapper进行对象集合的嵌套映射

C# 使用automapper进行对象集合的嵌套映射,c#,nested,automapper,C#,Nested,Automapper,我的对象结构是 Class cls1 { id, name, List<Address> address } Class cls2 { prop1, prop2, street, HouseNumber } 我想将cls1映射到cls2,其中cls2.street应该与Address对象的street属性映射 当我尝试Mapper.CreateMap.FormMemberGN=>gn.Street时,item=>item.M

我的对象结构是

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

Class cls2
{
    prop1,
    prop2,
    street,
    HouseNumber
}
我想将cls1映射到cls2,其中cls2.street应该与Address对象的street属性映射

当我尝试Mapper.CreateMap.FormMemberGN=>gn.Street时,item=>item.MapFromi=>i.address。。。它作为一个集合展出。
如何使用Automapper解析此映射每个cls2实例代表一个地址以及一些其他信息。cls1的每个实例都有一个地址集合。因此,不可能直接从cls1映射到cls2,除非假设cls1的每个实例中只有一个地址

为了克服这个问题,通过引入一个非规范化的对象来将单个cls1映射到多个cls2,该对象表示一个地址加上其父cls1。然后,可以从非规范化表示映射到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);
}
另一方面,如果每个cls1只有一个地址,则可以在映射中使用更直接的路由:

[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");
}