当前位置: 首页 > 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.xdnf.cn/news/1436545.html

相关文章:

  • QT(2)
  • MTK Linux DRM分析(二十九)- MTK mtk_dsi.c(Part.1)
  • Linux 环境配置 muduo 网络库详细步骤
  • Linux 文本处理三大利器:命令小工具和sed
  • 从理念到实践:三层解耦架构与“无系统”论
  • 基于web的高校学籍管理系统的设计与实现-(源码+LW+可部署)
  • CodeBuddy 在进化:我只输入了一个地址,完成了OneCode3.0基础开发环境的配置构建
  • JWT在线解密/JWT在线解码 - 加菲工具
  • kukekey在线搭建k8sV1.30.4版本
  • 从栈中取出K个硬币的最大面值和-分组背包
  • 【学Python自动化】 8. Python 错误和异常学习笔记
  • 2025年工科生职业发展证书选择与分析
  • 【模型学习】LoRA的原理,及deepseek-vl2下LoRA实现
  • 力扣242:有效的字母异位词
  • JetBrains 2025 全家桶 11合1 Windows直装(含 IDEA PyCharm、WebStorm、DataSpell、DataGrip等
  • C++类和对象(中)- 默认成员函数
  • 什么是数据库管理系统(DBMS)?RDBMS和NoSQL又是什么?
  • 第 2 讲:Kafka Topic 与 Partition 基础
  • Qwen3-Embedding-0.6B 模型结构
  • Go结构体详解:核心概念与实战技巧
  • Redis-底层数据结构篇
  • MySQL-表的约束(上)
  • 开发中使用——鸿蒙本地存储之收藏功能
  • LLM 能不能发展为 AGI?
  • 开源模型应用落地-模型上下文协议(MCP)-构建AI智能体的“万能插座”-“mcp-use”高级用法(十三)
  • 3.2-C++基础组件
  • 重新审视信任基石:公网IP证书对网络安全生态的影响
  • 【Go语言入门教程】 Go语言的起源与技术特点:从诞生到现代编程利器(一)
  • Cursor 教我学 Python
  • 英伟达Jetson Orin NX-YOLOv8s目标检测模型耗时分析