当前位置: 首页 > news >正文

C#类对象映射AutoMapper

AutoMapper 是 C# 中一款流行的 对象 - 对象映射库,核心作用是简化两个相似结构对象之间的属性赋值操作(例如将领域模型映射为 DTO、将数据实体映射为视图模型等),避免手动编写大量重复的 target.Property = source.Property 代码,提升开发效率并降低维护成本。
一、核心概念
在使用 AutoMapper 前,需理解两个核心角色:
1.源类型(Source Type):数据的来源对象(如代码中的 SignalLightItem)。
2.目标类型(Destination Type):数据的接收对象(如代码中的 SignalLight)。
3.映射配置(Mapping Configuration):定义源类型如何映射到目标类型的规则(是 AutoMapper 工作的核心)。
通过 NuGet 安装AutoMapper包:
通过「映射配置文件」定义规则(推荐)创建继承自
Profile 的类,在构造函数中定义源→目标的映射规则:

using AutoMapper;// 定义映射配置文件(一个 Profile 可包含多个映射规则)
public class SignalLightProfile : Profile
{public SignalLightProfile(){// 配置:SignalLightItem(源) → SignalLight(目标)// 1. 若属性名完全一致(如 Name、IsGreen 等),AutoMapper 会自动映射// 2. 若属性名不一致,需手动指定(你的场景无需此步骤)CreateMap<SignalLightItem, SignalLight>();}
}
var config = new MapperConfiguration(cfg =>
{cfg.CreateMap<SignalLightItem, SignalLight>(); // 直接定义映射
});
IMapper mapper = config.CreateMapper(); // 创建 IMapper 实例//使用新版库需要使用NullLoggerFactory
IMapper mapper;
MapperConfiguration config;
config = new MapperConfiguration(cfg =>
{//定义互换映射cfg.CreateMap<SignalLightItem, SignalLight>().ReverseMap(); // 直接定义映射},
new NullLoggerFactory());
mapper = config.CreateMapper(); // 创建 IMapper 实例

常见映射场景与高级用法
除了「属性名一致自动映射」,AutoMapper 还支持多种复杂场景:

  1. 属性名不一致的映射若源类型和目标类型的属性名不同
    (如源 UserName → 目标 Name),需通过 ForMember 手动指定:
public class UserProfile : Profile
{public UserProfile(){CreateMap<UserEntity, UserDto>()// 源.UserName → 目标.Name.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.UserName))// 源.Age → 目标.UserAge(若源为 null,指定默认值 0).ForMember(dest => dest.UserAge, opt => opt.MapFrom(src => src.Age ?? 0));}
}
  1. 忽略某些属性若目标类型的某个属性不需要从源类型映射
    (如目标的 IsDeleted 字段),可使用 Ignore:
CreateMap<SignalLightItem, SignalLight>().ForMember(dest => dest.IsDeleted, opt => opt.Ignore()); // 忽略 IsDeleted 属性
  1. 条件映射
    仅当源类型满足特定条件时,才映射某个属性:
CreateMap<SignalLightItem, SignalLight>()// 仅当源的 IsAlways 为 true 时,才映射目标的 IsGreen.ForMember(dest => dest.IsGreen, opt => opt.MapFrom(src => src.IsAlways ? src.IsGreen : false));
  1. 嵌套对象映射若源类型包含嵌套对象
    (如 UserEntity 包含 AddressEntity),目标类型包含对应的嵌套 DTO(UserDto 包含 AddressDto),需先配置嵌套对象的映射:
// 1. 先配置嵌套对象的映射
CreateMap<AddressEntity, AddressDto>();
// 2. 再配置主对象的映射(AutoMapper 会自动递归映射嵌套对象)
CreateMap<UserEntity, UserDto>();
  1. 自定义类型转换器若源类型和目标类型的转换逻辑复杂
    (如 string 转 DateTime、int 转 Enum),可自定义转换器:
// 1. 定义转换器:string(源)→ DateTime(目标)
public class StringToDateTimeConverter : IValueConverter<string, DateTime>
{public DateTime Convert(string source, ResolutionContext context){// 自定义转换逻辑(如处理多种日期格式)return DateTime.TryParse(source, out var result) ? result : DateTime.Now;}
}// 2. 在映射中使用转换器
CreateMap<OrderEntity, OrderDto>().ForMember(dest => dest.OrderTime, opt => opt.ConvertUsing(new StringToDateTimeConverter(), src => src.OrderTimeStr));

四、常见错误与解决方案
常见的错误:
错误类型原因解决方案
Missing type map configuration未:配置源→目标的映射规则按步骤 2 配置CreateMap<Source, Destination>()
NullReferenceException源对象为null,或源对象的嵌套属性为null1. 确保源对象非空;2. 使用MapFrom处理 null 场景(如src => src.NestedProp?.Value ?? “默认值”)
No default constructor目标类型没有无参构造函数(AutoMapper 默认需要无参构造函数创建目标对象)1. 给目标类型添加无参构造函数;2. 若无法添加,使用ConstructUsing自定义目标对象创建逻辑
Property ‘XXX’ is read-only目标类型的属性是只读的(如只有get没有set)1. 给目标属性添加set方法;2. 若为只读属性,使用ForMember结合MapFrom手动赋值(需确保属性可写)
五、总结
1.优先使用 Profile 配置文件:将映射规则集中管理,避免散落在业务代码中。
2.命名规范统一:尽量让源和目标的属性名一致,减少手动配置的工作量。
3.避免过度映射:只映射需要的属性,无关属性使用 Ignore 排除,提升性能。
4.测试映射规则:使用 AutoMapper 提供的

Configuration.AssertConfigurationIsValid() 方法,在启动时校验映射配置是否完整(避免运行时错误):
// 在 Program.cs 中校验配置
var mapperConfig = new MapperConfiguration(cfg => cfg.AddProfile<SignalLightProfile>());
mapperConfig.AssertConfigurationIsValid(); // 校验所有映射规则是否完整

5.依赖注入 IMapper:避免在代码中直接 new Mapper(),通过 DI 容器管理 IMapper 实例,便于测试和扩展。

http://www.dtcms.com/a/363956.html

相关文章:

  • JUC 并发集合:高效处理多线程数据共享的利器
  • 开源的聚合支付系统源码/易支付系统 /三方支付系统
  • More Effective C++ 条款24:理解虚拟函数、多继承、虚继承和RTTI的成本
  • 第一次用pyQt6制作JSON小工具
  • =Windows下VSCode配置SSH密钥远程登录
  • C语言中奇技淫巧08-使用alloca/__builtin_alloca从栈上分配空间
  • 打工人日报#20250902
  • 自动化运维-ansible中的循环应用
  • 机器学习入门,支持向量机
  • etf期权亏几个点就爆仓了?
  • 37.Ansible循环+常用过滤器
  • docker-compose的使用
  • 让AI成为您的眼睛:星眸(StarGaze),为盲人朋友点亮前行之路
  • MySQL8.0 新特性随笔
  • 基于B_S结构的校园报修管理系统设计与实现(代码+数据库+LW)
  • 设置STS(Spring Tool Suite),在格式化代码时for循环中的冒号左右都加上一个空格
  • 移动端网页调试实战,Safari Web Inspector 深度使用与对比分析
  • 关于?问号占位符的分析(主要以PHP为例)
  • C# 中这几个主流的 ORM(对象关系映射器):Dapper、Entity Framework (EF) Core 和 EF 6
  • C#基础(⑥动态链接库DLL)
  • Python 中将 JSON 字符串转为对象的几种方法对比
  • (五)Python控制结构(循环结构)
  • 最快的 C 语言 JSON 库 - yyjson
  • 爬虫-----最全的爬虫库介绍(一篇文章让你成为爬虫大佬,爬你想爬)
  • 【鸿蒙心迹】从疑惑到热爱:我的鸿蒙开发启蒙
  • Java消息中间件(RocketMQ)
  • Linux 文本处理实战手册
  • 【专栏升级】大模型应用实战并收录RAG专题,Agent专题,LLM重构数据科学流程专题,端侧AI专题,累计63篇文章
  • Redis 哨兵 (基于 Docker)
  • YOLO 目标检测:YOLOv5网络结构、Focus、CSP、自适应Anchor、激活函数SiLU、SPPF、C3