automapper映射必须在profile子类构造函数中调用createmap,且仅扫描构造函数体;嵌套映射需显式声明或用includemembers;禁止在mapfrom中写副作用逻辑;循环引用需preservereferences();addautomapper需传入正确程序集。

Profile 必须继承并只在构造函数里写 CreateMap
AutoMapper 只扫描 Profile 子类的构造函数体,其他位置(比如方法、静态块、字段初始化)写的 CreateMap<tsource tdestination>()</tsource> 会被完全忽略。这不是 bug,是设计限制。
常见错误包括:
- 把
CreateMap放在Configure方法里,结果运行时抛AutoMapperMappingException: Missing type map configuration - 在 Profile 里声明一个私有方法封装映射逻辑,然后在构造函数里调用——没用,AutoMapper 不执行方法体
正确写法只有这一种:
public class UserMappingProfile : Profile
{
public UserMappingProfile()
{
CreateMap<userentity userdto>();
CreateMap<userdto userentity>()
.ForMember(d => d.CreatedAt, o => o.Ignore());
}
}</userdto></userentity>
如果映射逻辑多,就拆成多个 Profile 类,别在一个构造函数里堆几十行 CreateMap。
ForMember 里别写空值判断或副作用逻辑
MapFrom 的 lambda 是用来生成表达式树的,不是普通委托。一旦你在里面写 src.Name ?? "N/A" 或 _repo.GetUserById(src.UserId),AutoMapper 就没法把它编译成高效委托,每次映射都走反射+动态执行,列表场景下 GC 压力明显上升。
替代方案要按场景选:
- 简单空值替换 → 用
NullSubstitute("N/A"),保留编译优化 - 需要条件判断(比如根据状态返回不同字符串)→ 自定义
IValueResolver<tsource tdestination tmember></tsource>,实现Resolve方法 - 绝对不要在
MapFrom里触发数据库查询、HTTP 调用、日志写入等副作用操作
顺便提醒:src.User?.Id 比 src.User.Id 安全,避免 NullReferenceException,这个问号是必须的。
嵌套对象和集合映射不会自动递归
AutoMapper 默认只做一层浅拷贝。即使 UserEntity.Profile 和 UserDto.Profile 都是 public 属性,也不会自动映射 Profile.Address.Street 到 ProfileDto.Street —— 它根本不会钻进去看。
解决方式分两类:
- 显式声明嵌套类型映射:
CreateMap<userprofile userprofiledto>()</userprofile>+CreateMap<userentity userdto>().ForMember(u => u.Profile, o => o.MapFrom(x => x.Profile))</userentity> - 扁平化映射(如
UserEntity.Profile.Street→UserDto.Street)→ 用IncludeMembers(x => x.Profile),但前提是Profile类型本身已有对应映射规则 - 集合映射(
List<userentity></userentity>→List<userdto></userdto>)不需要额外配置,只要单类型映射存在即可;但如果你用的是IEnumerable<t></t>或自定义集合类型,就得确认泛型约束是否匹配
循环引用(A→B→A)默认会抛异常,得加 PreserveReferences(),否则直接崩。
AddAutoMapper 传错程序集就等于没配
AddAutoMapper(typeof(UserProfile)) 看似简单,但背后依赖程序集扫描。如果 UserProfile 在独立类库(比如 MyApp.Mapping.dll),而你只传了 typeof(Program).Assembly,那这个 Profile 根本不会被发现。
排查方法很直接:
- 启动时加一句
mapper.ConfigurationProvider.AssertConfigurationIsValid(),它会在第一次调用前校验所有已加载的映射,报错信息里会明确说「未找到UserEntity→UserDto的映射」 - 确认
AddAutoMapper参数:推荐用AddAutoMapper(typeof(UserProfile).Assembly),比模糊的GetExecutingAssembly()更可靠 - 检查 Profile 类是否为
public,且不带abstract或internal修饰符——非 public 类不会被扫描到
最麻烦的情况是 Profile 里用了运行时才知道的泛型类型(比如 CreateMap<t tdto>()</t>),这种必须改用 IMapper.DynamicMap<tdto>(obj)</tdto>,但它不走预编译,性能差一截,能不用就别用。











