如何用AutoMapper实现带继承的多源对象映射?
AutoMapper多源对象映射解决方案(含Record类型)
1. 定义实体类型
先明确涉及的源对象和目标对象(包含record类型):
// 源对象 public class VolvoCarSource { public string Model { get; set; } public int Year { get; set; } public EngineSource Engine { get; set; } } // Record类型源对象 public record ColorSource(string ExteriorColor, string InteriorColor); public record EngineSource(int Horsepower, string FuelType); // 目标对象 public class VolvoCarDestination { public string ModelName { get; set; } public int ProductionYear { get; set; } public EngineDestination EngineInfo { get; set; } public string ExteriorColor { get; set; } public string InteriorColor { get; set; } } // Record类型目标子对象 public record EngineDestination(int Power, string Fuel);
2. AutoMapper配置方案
AutoMapper支持两种多源映射方式,可根据场景选择:
方案一:元组一次性映射(推荐)
将两个源对象包装为元组,一次性完成映射,配置更紧凑:
public class VolvoCarProfile : Profile { public VolvoCarProfile() { // 配置子对象映射:EngineSource → EngineDestination CreateMap<EngineSource, EngineDestination>() .ForMember(dest => dest.Power, opt => opt.MapFrom(src => src.Horsepower)) .ForMember(dest => dest.Fuel, opt => opt.MapFrom(src => src.FuelType)); // 配置多源映射:(VolvoCarSource, ColorSource) → VolvoCarDestination CreateMap<(VolvoCarSource Car, ColorSource Color), VolvoCarDestination>() .ForMember(dest => dest.ModelName, opt => opt.MapFrom(src => src.Car.Model)) .ForMember(dest => dest.ProductionYear, opt => opt.MapFrom(src => src.Car.Year)) .ForMember(dest => dest.EngineInfo, opt => opt.MapFrom(src => src.Car.Engine)) .ForMember(dest => dest.ExteriorColor, opt => opt.MapFrom(src => src.Color.ExteriorColor)) .ForMember(dest => dest.InteriorColor, opt => opt.MapFrom(src => src.Color.InteriorColor)); } }
方案二:分步映射(灵活更新)
先映射主对象,再用第二个源对象补充更新目标属性,适合需要部分字段更新的场景:
public class VolvoCarProfile : Profile { public VolvoCarProfile() { // 子对象映射 CreateMap<EngineSource, EngineDestination>() .ForMember(dest => dest.Power, opt => opt.MapFrom(src => src.Horsepower)) .ForMember(dest => dest.Fuel, opt => opt.MapFrom(src => src.FuelType)); // 主对象映射:VolvoCarSource → VolvoCarDestination CreateMap<VolvoCarSource, VolvoCarDestination>() .ForMember(dest => dest.ModelName, opt => opt.MapFrom(src => src.Model)) .ForMember(dest => dest.ProductionYear, opt => opt.MapFrom(src => src.Year)) .ForMember(dest => dest.EngineInfo, opt => opt.MapFrom(src => src.Car.Engine)); // 补充映射:ColorSource → VolvoCarDestination(仅更新颜色字段) CreateMap<ColorSource, VolvoCarDestination>() .ForMember(dest => dest.ExteriorColor, opt => opt.MapFrom(src => src.ExteriorColor)) .ForMember(dest => dest.InteriorColor, opt => opt.MapFrom(src => src.InteriorColor)); } }
3. 映射执行示例
方案一执行代码:
// 初始化AutoMapper var config = new MapperConfiguration(cfg => cfg.AddProfile<VolvoCarProfile>()); var mapper = config.CreateMapper(); // 构造源数据 var carSource = new VolvoCarSource { Model = "XC90", Year = 2024, Engine = new EngineSource(250, "Petrol") }; var colorSource = new ColorSource("Crystal White", "Charcoal"); // 执行元组映射 var dest = mapper.Map<VolvoCarDestination>((carSource, colorSource));
方案二执行代码:
// 初始化AutoMapper var config = new MapperConfiguration(cfg => cfg.AddProfile<VolvoCarProfile>()); var mapper = config.CreateMapper(); // 构造源数据 var carSource = new VolvoCarSource { Model = "XC90", Year = 2024, Engine = new EngineSource(250, "Petrol") }; var colorSource = new ColorSource("Crystal White", "Charcoal"); // 分步映射 var dest = mapper.Map<VolvoCarDestination>(carSource); mapper.Map(colorSource, dest);
关键说明
- Record类型的映射与普通类完全兼容,AutoMapper会自动处理其属性或构造函数映射,无需额外配置。
- 两种方案的映射结果与手动映射逻辑完全一致,可根据业务场景选择更合适的方式。
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

