代码之家  ›  专栏  ›  技术社区  ›  Linda Lawton - DaImTo

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

  •  0
  • Linda Lawton - DaImTo  · 技术社区  · 5 年前

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

    在这个简单的最小可复制示例中,我创建了一个动物园类,其中包含一个动物列表,这就是目的地。源代码是MammelHouse类,它包含pig和cow对象的列表。

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

    我目前的解决方案是单独映射每个对象类型,然后将它们添加到主对象中,因为我的实际应用程序目前有十种不同的类型,这不是最佳解决方案。我希望有一种方法可以直接用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";
    }
    

    我所看到的

    • 添加AfterMap这不是正确的方向,因为我实际上有两个以上。
    • 目前正在尝试使用自定义映射器使其工作,但这也不起作用,因为我无法将映射器对象传递给它。

    根据评论更新

    从评论中可以看出,康卡特显然是不被允许的。

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

    enter image description here

    尝试增加范围这也不起作用,因为牛和猪不是同一类型

    opt.MapFrom(src => src.Cows.AddRange(src.Pigs)));
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   Akshay G    5 年前

    添加一个常见的 interface IMammel Cow Pig 然后使用 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";
    }
    

    自动映射配置

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