使用AutoMapper映射含多可空子计划的Plan实体至PlanDto的问题
嘿,我来帮你搞定AutoMapper的这个映射需求!
首先我先明确下你的场景:你的Plan实体里有多个单独的可空子计划属性(比如PlanChild1、PlanChild2这类),而PlanDto需要把所有非空的子计划统一收集到一个列表里,对吧?之前你用foreach手动实现了,现在想换成AutoMapper来自动化这个过程,没问题!
先补全下实体和DTO的定义(方便后续示例)
假设你的实体和DTO大概是这样的(补全你没写完的部分):
// 实体类 public class Plan { public virtual int Id { get; set; } public DateTime Date { get; set; } public virtual PlanDetail? PlanChild1 { get; set; } public virtual PlanDetail? PlanChild2 { get; set; } public virtual PlanDetail? PlanChild3 { get; set; } // 更多子计划属性... } public class PlanDetail { public int Id { get; set; } public string Name { get; set; } = string.Empty; } // DTO类 public class PlanDto { public int Id { get; set; } public DateTime Date { get; set; } public List<PlanDetailDto> Children { get; set; } = new List<PlanDetailDto>(); } public class PlanDetailDto { public int Id { get; set; } public string Name { get; set; } = string.Empty; }
方案1:手动指定子计划属性(适合属性数量少的情况)
直接在AutoMapper的映射配置里,把所有子计划属性放到临时列表,过滤掉null后映射成DTO列表:
var mapperConfig = new MapperConfiguration(cfg => { // 先配置PlanDetail到PlanDetailDto的基础映射 cfg.CreateMap<PlanDetail, PlanDetailDto>(); // 配置Plan到PlanDto的映射,重点处理Children列表 cfg.CreateMap<Plan, PlanDto>() .ForMember(dest => dest.Children, opt => opt.MapFrom(src => // 把所有子计划属性放到列表,过滤非空项 new List<PlanDetail?> { src.PlanChild1, src.PlanChild2, src.PlanChild3 } .Where(child => child != null) .ToList() )); });
AutoMapper会自动帮你把过滤后的PlanDetail实例转换成PlanDetailDto,不用手动逐个转换。
方案2:用反射自动收集子计划(适合属性数量多或后续可能新增的情况)
如果你的子计划属性很多,不想一个个手动列出来,用反射可以更灵活地收集所有PlanDetail类型的属性:
var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<PlanDetail, PlanDetailDto>(); cfg.CreateMap<Plan, PlanDto>() .ForMember(dest => dest.Children, opt => opt.MapFrom(src => // 反射获取Plan类中所有PlanDetail或可空PlanDetail类型的属性 typeof(Plan).GetProperties() .Where(p => p.PropertyType == typeof(PlanDetail) || p.PropertyType == typeof(PlanDetail?)) // 取出属性值并转为PlanDetail类型 .Select(p => p.GetValue(src) as PlanDetail) // 过滤空值 .Where(child => child != null) .ToList() )); });
这样以后新增子计划属性(比如PlanChild4),完全不用修改映射配置,自动就能被收集到列表里。
验证使用
配置好之后,直接用AutoMapper的实例进行映射就可以了:
var mapper = mapperConfig.CreateMapper(); // 构造测试用的Plan实体 var testPlan = new Plan { Id = 1, Date = DateTime.Now, PlanChild1 = new PlanDetail { Id = 101, Name = "子计划A" }, PlanChild3 = new PlanDetail { Id = 103, Name = "子计划C" }, // PlanChild2留空 }; // 映射成DTO var planDto = mapper.Map<PlanDto>(testPlan); // 此时planDto.Children里会包含子计划A和C对应的DTO对象
注意事项
- 确保你已经安装了AutoMapper NuGet包:可以用
Install-Package AutoMapper(Package Manager)或dotnet add package AutoMapper(.NET CLI) - 如果你的子计划属性是EF Core的延迟加载属性(带
virtual关键字),要确保映射前已经加载了这些属性(比如用Include),否则可能会得到空值或者触发额外的数据库查询。
内容的提问来源于stack exchange,提问作者Mohammad Shadmehr
相关产品推荐
相关产品推荐

