C# AutoMapper使用方法 C#如何实现对象到对象的映射

3次阅读

automapper v10+必须显式创建imapper实例,禁用静态mapper;需配置createmap并调用assertconfigurationisvalid()校验,推荐使用profile类组织映射逻辑。

C# AutoMapper使用方法 C#如何实现对象到对象的映射

AutoMapper 初始化必须调用 CreateMapper()Mapper.Initialize()

新版 AutoMapper(v10+)已移除静态 Mapper 类,直接调用 Mapper.Map<t>()</t> 会抛出 System.NULLReferenceException: 'Object reference not set to instance of an object.'。必须显式创建 IMapper 实例。

  • 推荐在 Program.cs(.NET 6+)或 Startup.cs 中配置:
var mapperConfig = new MapperConfiguration(cfg => {     cfg.CreateMap<Source, Destination>(); }); IMapper mapper = mapperConfig.CreateMapper(); // 关键:不能省略
  • 若用依赖注入(如 ASP.NET Core),应注册为单例:
services.AddAutoMapper(cfg => cfg.CreateMap<Source, Destination>()); // 自动发现 Profile 更安全
  • 手动 new MapperConfiguration 后忘记调用 CreateMapper() 是最常见空引用原因

CreateMap<tsource tdestination>()</tsource> 默认只映射同名同类型的属性

AutoMapper 不会自动转换类型或处理嵌套对象,比如 DateTimeStringList<int></int>int[]、或 User.Profile.NameUserDto.ProfileName,这些都需要显式配置。

  • 基础映射(字段名和类型完全一致)可直接使用:
cfg.CreateMap<User, UserDto>(); // Name → Name, Id → Id ✅
  • 字段名不同需用 ForMember
cfg.CreateMap<User, UserDto>()     .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.FirstName + " " + src.LastName));
  • 忽略某字段用 Ignore()
.ForMember(dest => dest.PasswordHash, opt => opt.Ignore())
  • 嵌套对象默认不递归映射,需单独声明 CreateMap
cfg.CreateMap<UserProfile, UserProfileDto>(); cfg.CreateMap<User, UserDto>()     .ForMember(u => u.Profile, opt => opt.MapFrom(x => x.Profile));

运行时出现 AutoMapper.AutoMapperMappingException 的典型原因

这个异常通常包裹更具体的子错误,直接看 InnerExceptionMessage 才能定位。常见触发点有:

  • 目标类型无公共无参构造函数(如 record 在旧版 AutoMapper 中可能失败,v12+ 支持更好)
  • 源/目标属性类型不兼容且未配置 ConvertUsingMapFrom
  • 循环引用未启用 cfg.AllowNullCollections = true 或未配置 PreserveReferences()
  • 使用了 MapFromLambda 访问了 null 源属性(例如 src.Address.Streetsrc.Address 为 null)→ 应改用 UseValue 或前置空判断

调试建议:在 MapperConfiguration 构造后立即调用 AssertConfigurationIsValid(),它会在启动时主动校验所有映射规则是否可执行:

var config = new MapperConfiguration(cfg => { /* ... */ }); config.AssertConfigurationIsValid(); // 抛出明确的验证失败信息

Profile 类更适合中大型项目,避免配置散落在 Startup 中

把映射规则封装继承Profile 的类,能解耦、复用、便于单元测试。AutoMapper 会自动扫描程序集中所有 Profile 子类(前提是用了 AddAutoMapper(Assembly))。

  • 定义一个 Profile:
public class UserMappingProfile : Profile {     public UserMappingProfile()     {         CreateMap<User, UserDto>()             .ForMember(d => d.CreatedAt, o => o.ConvertUsing<DateTimeToIsoStringConverter>());     } }
  • 注册时传入程序集:
services.AddAutoMapper(typeof(UserMappingProfile).Assembly);
  • 自定义转换器需实现 ITypeConverter<tsource tdestination></tsource>,比在 CreateMap 里写 lambda 更易测试和复用

Profile 不是语法糖,它是组织映射逻辑的实际边界——尤其当多个 DTO 共享同一组转换规则时,漏掉一个 CreateMap 或错放 Profile 到未被扫描的程序集,就会静默失败。

text=ZqhQzanResources