Automapper 6.2.2如何通过ReverseMap实现条件式反扁平化?
解决AutoMapper ReverseMap()反扁平化时自动创建空对象的问题
这个问题我之前也碰到过——AutoMapper的ReverseMap()在处理反扁平化时,默认会自动初始化嵌套对象,哪怕源的扁平化属性没有值,这确实很头疼。你用Condition没生效的原因是,AutoMapper在判断条件之前就已经创建了目标嵌套对象,所以条件只能控制是否赋值,没法阻止对象被初始化。
下面给你几个正规的解决方案:
方案1:在MapFrom中直接判断并返回null
最直接的方式是在MapFrom里根据源属性的值决定是否创建对象,没有值时返回null,这样AutoMapper就不会生成空对象了:
cfg.CreateMap<Entity, DTO>() .ReverseMap() .ForMember(dest => dest.UnflattenedType, opt => { opt.MapFrom(src => src.FlattenedId.HasValue ? new UnflattenedType { Id = src.FlattenedId.Value } : null); });
方案2:单独配置反向映射(替代ReverseMap())
如果ReverseMap()生成的默认映射不够灵活,你可以放弃它,手动配置反向映射,这样能更精准地控制逻辑:
// 正向映射保持不变 cfg.CreateMap<Entity, DTO>(); // 手动配置反向映射:DTO → Entity cfg.CreateMap<DTO, Entity>() .ForMember(dest => dest.UnflattenedType, opt => { // 只有当FlattenedId有值时才映射这个成员 opt.Condition(src => src.FlattenedId.HasValue); // 明确指定映射逻辑 opt.MapFrom(src => new UnflattenedType { Id = src.FlattenedId.Value }); // 确保条件不满足时目标属性为null opt.NullSubstitute(null); });
方案3:使用PreCondition(针对AutoMapper 6.x)
PreCondition会在AutoMapper尝试创建目标对象之前执行判断,能有效阻止空对象的生成:
cfg.CreateMap<Entity, DTO>() .ReverseMap() .ForMember(dest => dest.UnflattenedType, opt => { opt.PreCondition(src => src.FlattenedId.HasValue); opt.MapFrom(src => new UnflattenedType { Id = src.FlattenedId.Value }); opt.NullSubstitute(null); });
为什么你的Condition无效?
Condition是在AutoMapper已经创建了目标对象之后才进行判断的,这时候空对象已经存在了,所以它只能控制是否给对象的属性赋值,没法取消对象的创建。而PreCondition或者直接在MapFrom返回null,都是在对象创建前就决定了要不要生成它,这才是解决问题的核心。
你的临时AfterMap方案虽然能生效,但会多一步额外的赋值操作,上面的方案都是在映射阶段就处理好,更符合AutoMapper的设计逻辑。
内容的提问来源于stack exchange,提问作者user999272
相关产品推荐
相关产品推荐

