如何在不覆盖值的情况下映射列表

How to map lists without overwriting values

我有一个包含两种不同对象类型的对象,我试图将它映射到另一个包含单个列表的对象。

在这个简单的最小可重现示例中,我创建了一个动物园 class,其中包含一个动物列表,这是目的地。来源是 MammelHouse class,其中包含猪和牛对象的列表。

我的问题是,当我尝试将猪添加到列表中时,它覆盖了已经写入的奶牛。我需要将这两个对象添加到此列表中。

我目前的解决方案是单独映射每个对象类型,然后将它们添加到主对象,因为我的实际应用程序目前有十种不同的类型,这不是最佳解决方案。我希望有一种方法可以直接使用 automapper 解决这个问题。

当前映射尝试

public class MappingResourceZoo : Profile
    {
        public MappingResourceZoo()
        {
            CreateMap<MammalHouse, Zoo>()
                .ForMember(dest => dest.Animals, opt => opt.MapFrom(src => src.Cows))
                .ForMember(dest => dest.Animals, opt => opt.MapFrom(src => src.Pigs));

            CreateMap<Cow, Animal>()
                .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Species));
            
            CreateMap<Pig, Animal>()
                .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Species));
        }
    }

这个映射的问题是当猪被映射时,奶牛被覆盖了。所以测试失败。,

测试

    [Fact]
    public void TestsConcatAddress()
    {
        var src = new MammalHouse()
        {
            Cows = new List<Cow>()
            {
                new Cow() {Species= "Chocolate cow"},
                new Cow() {Species= "Vanilla cow"}
            },
            Pigs = new List<Pig>()
            {
                new Pig() { Species= "Bacon"},
                new Pig() { Species= "Sausage"}
            }
        };

        var config = new MapperConfiguration(cfg => cfg.AddProfile<MappingResourceZoo>());
        var mapper = config.CreateMapper();
        var response = mapper.Map<Zoo>(src);

        response.Animals.Should().NotBeNull().And.HaveCount(4); ;
    }

这是您测试乐趣的模型。这两个模型来自第三方系统,无法更改。

// The Zoo model comes from third party api 1


public class Zoo
{
    public List<Animal> Animals { get; set; }
    
}
public class Animal 
{
    public string Name { get; set; }
}

// The mammal model comes from third party api Two.

public class MammalHouse
{
    public List<Cow> Cows { get; set; }
    public List<Pig> Pigs { get; set; }
    
}

public class Cow
{
    public string Species{ get; set; } = "cow";
}    

public class Pig
{
    public string Species{ get; set; } = "pig";
}

我看过的

根据评论更新

从评论中建议显然不允许使用 Concat。

CreateMap<MammalHouse, Zoo>()
            .ForMember(dest => dest.Animals, opt => opt.MapFrom(src => src.Cows.Concat(src.Pigs)));

也试过添加范围,但还是不行,因为牛和猪不是同一种类型

opt.MapFrom(src => src.Cows.AddRange(src.Pigs)));

CowPig中添加一个普通的interfaceIMammel然后使用Concat

型号

public interface IMammel 
{

}
public class Animal 
{
    public string Name { get; set; }

}
public class Pig : IMammel 
{
    public string Species { get; set; } = "pig";
}


public class Cow : IMammel 
{
    public string Species { get; set; } = "cow";
}

AutoMapper 配置

public class MappingResourceZoo : Profile
{
    public MappingResourceZoo()
    {
        CreateMap<Cow, Animal>()
         .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Species));

        CreateMap<Pig, Animal>()
            .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Species));

        CreateMap<MammalHouse, Zoo>()
            .ForMember(dest => dest.Animals, opt => opt.MapFrom(src => src.Cows.Concat<IMammel>(src.Pigs)));

    } 
}