Mapster 默认不映射私有字段或 private set/init 属性,需显式设置 IgnoreNonPublic = false;“No type adapter found”因命名不匹配或未注册嵌套类型映射,可启用 Flexible 策略解决;Adapt() 用于内存对象映射,ProjectToType() 专用于 IQueryable 数据库查询优化。

Mapster 默认不自动映射私有字段或带 setter 限制的属性(比如 private set 或 init),新手常以为“只要属性名一样就能映射”,结果发现目标对象字段始终为默认值——这是最常踩的坑。
如何让 Mapster 映射 private set / init 属性
Mapster 默认只映射 public getter + public setter 的属性。遇到 public string Name { get; private set; } 或 public int Age { get; init; },必须显式启用非公共访问:
- 全局配置:在启动时调用
TypeAdapterConfig.GlobalSettings.Default.IgnoreNonPublic = false; - 或针对某类型单独配置:
TypeAdapterConfig<tsource tdestination>.NewConfig().RequireExplicitMapping(false).IgnoreNonPublic(true);</tsource> - 注意:启用
IgnoreNonPublic = true后,Mapster 会尝试通过反射写入私有成员,.NET 6+ 在 AOT 编译下可能失败,开发阶段可用,发布前需验证
Mapster 报错 “No type adapter found” 怎么办
这个错误本质是 Mapster 没找到从源类型到目标类型的映射规则,常见于以下场景:
- 两个类字段名不完全一致(比如源是
FirstName,目标是First_Name),且未配置命名匹配策略 - 存在嵌套对象但没注册对应映射(
Address→AddressDto需单独TypeAdapterConfig<address addressdto>.NewConfig();</address>) - 使用了泛型类型但没指定具体泛型参数(如
List<t></t>不能直接映射,要写成List<source></source>→List<dest></dest>) - 解决办法:加一行
TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy = NameMatchingStrategy.Flexible;,它能处理大小写、下划线/驼峰混用
什么时候该用 Mapster.Adapt() 而不是 Mapster.ProjectToType()
Adapt() 是运行时对象实例映射,适合单个对象或小集合;ProjectToType() 是表达式树翻译,专用于 IQueryable(比如 EF Core 查询),能将映射逻辑下推到 SQL 层:
- 对数据库查询结果做 DTO 转换,必须用
queryable.ProjectToType<userdto>()</userdto>,否则会把全部字段查出来再内存映射,性能崩盘 -
Adapt()支持自定义转换函数(如cfg.From(src => src.CreatedAt.ToString("yyyy-MM-dd"))),ProjectToType()只支持能被 EF Core 表达式树解析的操作 - 若误把
ProjectToType()用在普通 List 上,会抛出InvalidOperationException: The source IQueryable doesn't implement IAsyncEnumerable
Mapster 的配置是静态的,一旦注册就全局生效;不同模块如果对同一类型对有冲突的映射规则(比如一个要忽略 Password,另一个要映射),得用命名配置隔离,而不是反复调用 NewConfig() —— 后者不会覆盖已有配置,容易埋下静默失效的隐患。


















