跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C#怎么使用AutoMapper对象映射_C#实体类自动映射教程【实战】

AutoMapper需在启动时一次性配置并复用IMapper实例;Profile构造函数中注册CreateMap;ForMember需防null;集合映射须先配单类型;EF查询应使用ProjectTo而非Map;务必调用AssertConfigurationIsValid()校验配置。 AutoMapper 不是“装完就能用”的函数式工具,必须在应用启动时完成一次性配置并复用
IMapper
实例;运行时反复 new
MapperConfiguration
或在 Controller 里手写映射逻辑,大概率导致性能骤降、空引用异常或静默映射失败。 Profile 类必须在构造函数里写 CreateMap,别放别处 AutoMapper 只扫描
Profile
子类的构造函数体,其他位置(比如方法、字段初始化、静态构造器)写的
CreateMap()
全部被忽略。 ✅ 正确:在
UserProfile : Profile
的构造函数中调用
CreateMap()
❌ 错误:把
CreateMap
拆到单独方法里再从构造函数调用——AutoMapper 不会追踪方法调用链 ⚠️ 注意:如果
Profile
定义在独立类库中,
AddAutoMapper(typeof(UserProfile).Assembly)
必须显式传入该程序集,否则扫描不到 ForMember 映射字段名不一致时,lambda 参数要防 null 默认只匹配大小写不敏感的同名属性。一旦实体是
CreatedDate
、DTO 是
CreatedAt
,或者要取
User?.Id
,就必须用
ForMember
+
MapFrom
,且 lambda 中的源对象访问路径得带空值安全操作。 ✅ 推荐:
.ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.User?.Id))
—— 避免
NullReferenceException
❌ 危险:
.ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.User.Id))
——
src.User
为 null 时直接崩 ? 空值替代优先用
NullSubstitute("N/A")
,而不是
MapFrom(src => src.Name ?? "N/A")
,后者绕过表达式树编译,高频列表映射时 GC 压力明显上升 集合映射失败?先确认单类型映射已注册
_mapper.Map>(users)
看似合理,但 AutoMapper 不会自动推导集合规则——它只基于你已声明的
CreateMap()
来展开泛型。 C知道 CSDN推出的一款AI技术问答工具 下载 ✅ 正确顺序:先配
CreateMap()
,再调
Map>
❌ 错误假设:“我配了单个类型,集合就该自动支持”——没配单类型映射,集合映射会静默返回空列表或抛
AutoMapperMappingException
⚠️ 特别注意:
IEnumerable
和
List
行为不同,若目标是
IReadOnlyCollection
,需额外确认泛型约束是否兼容 EF 查询别用 Map,改用 ProjectTo 避免 N+1 对
IQueryable
直接
Map>
会强制执行查询、加载全部实体到内存,再做映射——完全失去 EF 的延迟加载和 SQL 投影优势。 ✅ 正确做法:
context.Users.ProjectTo(mapper.ConfigurationProvider)
—— 生成 SELECT 字段级投影 SQL,不查多余字段 ❌ 错误写法:
context.Users.ToList().Select(x => mapper.Map(x)).ToList()
—— 全量查库 + 内存遍历,DB 和 GC 双重压力 ⚠️ 注意:
ProjectTo
要求所有映射字段都能转成 Expression,所以
MapFrom
里不能有方法调用(如
_repo.GetUserById()
),也不能用复杂业务逻辑 最常被跳过的其实是
AssertConfigurationIsValid()
—— 它不解决运行时逻辑错误,但能提前暴露类型未注册、嵌套映射缺失、只读属性无 setter 等配置硬伤。开发阶段漏掉这句,上线后字段为 null 往往要花半天排查。

相关文章