如何使用Mapster覆盖默认映射?克隆配置修改未生效如何解决
问题根因
你遇到的映射不生效问题源于Mapster的两个机制特性,同时你的代码存在不合理的配置注册逻辑:
- 默认映射写在控制器构造函数中,每次控制器被实例化都会重复注册全局映射,属于无效重复操作,应该移到项目启动入口全局注册一次即可。
- Mapster默认的配置继承逻辑下,先注册的全局规则优先级高于克隆配置中新增的同属性规则:
- 全局先注册了
TitleDto的映射规则,后续克隆配置新增的同属性映射不会覆盖原有值 - 全局已经将
IgnoreTest标记为忽略,忽略规则优先级高于普通映射规则,即使后续新增映射也不会赋值
- 全局先注册了
解决方法
使用Mapster提供的Fork方法生成临时配置,配合优先级设置或规则清除即可实现覆盖,两种实现方式可选:
方式1:仅覆盖需要修改的属性(推荐,继承原有其他映射规则)
第一步:将默认映射移到启动入口全局注册
在Program.cs等项目启动逻辑中注册一次默认规则:
TypeAdapterConfig<Course, CourseDto>.ForType() .Map(dest => dest.CourseIDDto, src => src.CourseID) .Map(dest => dest.CreditsDto, src => src.Credits) .Map(dest => dest.TitleDto, src => src.Title + " DEFAULT") .Ignore(d => d.IgnoreTest) .Map(dest => dest.EnrollmentsDto, src => src.Enrollments);
第二步:修改接口中的临时配置逻辑
[HttpGet("course")] [EnableQuery] public IQueryable<CourseDto> GetCourses() { var query = _context.Courses.AsNoTracking(); // Fork生成临时配置,继承全局规则同时支持局部修改 var tempConfig = TypeAdapterConfig.GlobalSettings.Fork(config => { config.ForType<Course, CourseDto>() // 取消IgnoreTest的全局忽略规则 .IgnoreIf((_, _) => false, d => d.IgnoreTest) // 覆盖TitleDto映射,设置最高优先级 .Map(dest => dest.TitleDto, src => src.Title + " over-CLONE", opt => opt.MapOrder = -1) // 新增自定义映射 .Map(dest => dest.AnotherTestDto, src => src.Title + " NEW-CLONE") // 覆盖IgnoreTest映射,设置最高优先级 .Map(dest => dest.IgnoreTest, src => src.Title + " over-IGNORE-CLONE", opt => opt.MapOrder = -1); }); return query.ProjectToType<CourseDto>(tempConfig); }
参数说明:
MapOrder = -1:Mapster按MapOrder从小到大的顺序执行映射,值越小优先级越高,设置为-1会优先执行覆盖原有规则IgnoreIf((_, _) => false, d => d.IgnoreTest):取消原有忽略标记,允许属性被赋值
方式2:完全重置该类型的所有映射规则
如果不需要继承原有任何映射规则,可以直接清空后重新定义:
var tempConfig = TypeAdapterConfig.GlobalSettings.Fork(config => { config.ForType<Course, CourseDto>() .Clear() // 清空该类型所有原有映射规则 // 重新定义所有需要的映射 .Map(dest => dest.CourseIDDto, src => src.CourseID) .Map(dest => dest.CreditsDto, src => src.Credits) .Map(dest => dest.TitleDto, src => src.Title + " over-CLONE") .Map(dest => dest.AnotherTestDto, src => src.Title + " NEW-CLONE") .Map(dest => dest.IgnoreTest, src => src.Title + " over-IGNORE-CLONE") .Map(dest => dest.EnrollmentsDto, src => src.Enrollments); });
修改后返回结果就会符合预期。
内容的提问来源于stack exchange,提问作者Petr S
相关产品推荐
相关产品推荐

