AutoMapper 必须全局单例配置并复用,IMapper 要注册为单例,v10+ 已移除静态 Mapper;Profile 需显式传入程序集,嵌套映射需手动配置,推荐使用 SourceGenerator 提升启动性能。

AutoMapper 不是“用一下就完事”的工具,它必须配置一次、全局复用;否则每次 new Mapper 或反复构建 MapperConfiguration,性能会断崖式下跌,尤其在 Web API 高并发场景下。
IMapper 必须单例注入,不能每次 new
新版 AutoMapper(v10+)已移除静态 Mapper 类,直接调用 Mapper.Map<T>() 会抛 NullReferenceException。根本原因是你没拿到有效的 IMapper 实例。
- ❌ 错误写法:
var mapper = new Mapper(new MapperConfiguration(cfg => cfg.CreateMap<A, B>()));—— 每次请求都重建配置,反射扫描+表达式编译开销极大 - ✅ 正确做法:在
Program.cs中注册为单例:services.AddAutoMapper(typeof(YourProfile)); - 若
YourProfile在独立类库,必须显式传入程序集:services.AddAutoMapper(typeof(MyProfile).Assembly); -
MapperConfiguration是线程安全的,但IMapper实例也推荐单例——它内部缓存了编译后的映射委托,重复创建等于放弃所有优化
“Missing type map configuration” 错误怎么查
这个报错不是代码写错了,而是 AutoMapper 根本没加载到你的映射规则。90% 的情况是 Profile 没被发现或泛型方向反了。
- 检查
AddAutoMapper()是否传入了含Profile子类的程序集;如果只传typeof(Program),而 Profile 在Core.dll里,那就完全失效 - 确认
CreateMap<Source, Destination>()的泛型顺序:它定义的是「从 Source 映射到 Destination」,写成CreateMap<Destination, Source>()不报错,但逻辑全反 - 避免隐式转换干扰:如果
Source和Destination之间存在自定义implicit operator,AutoMapper 可能跳过字段映射直接调用它,导致部分字段静默丢失 - 开发期加一句
mapperConfig.AssertConfigurationIsValid();,能在启动时提前暴露未覆盖的类型组合
嵌套对象不自动映射,必须显式声明
AutoMapper 默认只做浅拷贝。哪怕 UserDto.Profile.Address.Street 和 UserEntity.Profile.Address.Street 字段名完全一致,也不会自动递归映射——它连 Profile 这一级都不会进。
- 必须单独配
CreateMap<AddressDto, AddressEntity>(),否则Address属性永远是 null - 再在
CreateMap<UserDto, UserEntity>()中指定路径:.ForMember(x => x.Address, opt => opt.MapFrom(y => y.Profile.Address)) - 如果只是扁平化(比如把
User.Profile.Name映射成UserDto.ProfileName),可用IncludeMembers(x => x.Profile)简化,但它不会自动展开深层嵌套 - 别依赖“同名属性自动钻取”——AutoMapper 没这功能,这是常见误解
为什么 .NET 6+ 推荐用 SourceGenerator 而非运行时反射
运行时反射构建映射配置是启动慢、冷启动卡顿的主因。尤其当项目引用大量程序集,AutoMapper 扫描所有类型时,首次 MapperConfiguration 构建可能延迟数百毫秒。
-
AutoMapper.SourceGenerator把映射逻辑移到编译期,生成Mapper.g.cs,彻底去掉运行时反射和Expression.Compile开销 - 需手动启用:在项目文件中添加
<PackageReference Include="AutoMapper.SourceGenerator" Version="12.0.0" PrivateAssets="all" />,并确保启用生成器 - 生成的代码可调试、可审查,但代价是:新增映射类型后必须重新生成,且不支持运行时动态注册 Profile
- 对 CI/CD 友好,但本地开发时容易忽略 “没生成” 导致映射失效——这是最隐蔽的坑


















