AutoMapper类映射到record时报错需0参或仅可选参构造函数如何解决
问题原因
- 你使用的位置式record(通过括号声明参数的record类型)默认没有无参构造函数,AutoMapper默认优先通过构造函数完成映射,而你配置的
ForMember属于属性赋值规则,不会作用于构造函数参数注入阶段,因此无法匹配到符合要求的构造函数。 - 现有代码还存在两个隐性错误:
- 你的数据库实体类名为
AccessTokens,但CreateMap的第一个泛型参数写的是AccessToken,类名不一致会导致映射规则不生效 DateTime.ToShortDateString()方法不支持传入格式参数,你需要改用ToString("yyyy-MM-dd")实现日期格式化
- 你的数据库实体类名为
- 单独调用
DisableCtorValidation()仅会关闭构造函数校验,不会修改AutoMapper优先走构造函数映射的逻辑,因此依旧会抛出错误。
解决方案
你可以选择以下任意一种方案解决问题:
方案1:配置构造函数参数映射(推荐,保留位置record的原有写法)
直接针对record的构造参数配置映射规则,AutoMapper会按照构造参数的要求完成注入:
// 注意第一个泛型参数和实体类名保持一致为AccessTokens CreateMap<AccessTokens, AccessTokenResponseDto>() .ForCtorParam("Token", opt => opt.MapFrom(src => src.Value)) .ForCtorParam("ExpiryDate", opt => opt.MapFrom(src => src.ExpiryDate.ToString("yyyy-MM-dd")));
剩余Id、FriendlyName参数和源实体属性名完全一致,AutoMapper会自动完成匹配。
方案2:给record显式添加无参构造函数
修改record的定义,显式声明无参构造,让AutoMapper可以先实例化对象,再使用你原来写的ForMember属性映射规则:
public record AccessTokenResponseDto { public int Id { get; init; } public string Token { get; init; } public string ExpiryDate { get; init; } public string FriendlyName { get; init; } // 显式添加无参构造 public AccessTokenResponseDto() {} // 可保留原有带参构造方便其他场景使用 public AccessTokenResponseDto(int id, string token, string expiryDate, string friendlyName) { Id = id; Token = token; ExpiryDate = expiryDate; FriendlyName = friendlyName; } }
修改后你原有ForMember格式的映射配置即可正常生效。
方案3:强制AutoMapper跳过构造函数注入逻辑
在映射配置中显式指定构造逻辑,强制AutoMapper走属性赋值路径:
CreateMap<AccessTokens, AccessTokenResponseDto>() .DisableCtorValidation() .ForMember(dest => dest.ExpiryDate, opt => opt.MapFrom(src => src.ExpiryDate.ToString("yyyy-MM-dd"))) .ForMember(dest => dest.Token, opt => opt.MapFrom(src => src.Value)) // 显式指定构造逻辑,参数先填默认值,后续会通过属性赋值覆盖 .ConstructUsing(_ => new AccessTokenResponseDto(default, default, default, default));
内容的提问来源于stack exchange,提问作者PalBo
相关产品推荐
相关产品推荐

