You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

源类含Original属性且目标为record时,AutoMapper为何抛出NullReferenceException?

为何AutoMapper在源类含Original属性且目标为record时抛出NullReferenceException?

问题重现

你提供的代码运行时会触发NullReferenceException,但修改源属性名或把目标改为普通类后即可正常运行:

using AutoMapper;

var mapper = new MapperConfiguration(conf =>
{
    conf.CreateMap<From, To>();
}).CreateMapper();

var from = new From();
var to = mapper.Map<To>(from);

public class From
{
    public string? Original { get; set; }
    public bool BoolProp { get; set; }
}

public record To
{
    public bool BoolProp { get; init; }
}

原因分析

这是AutoMapper处理record类型的特殊逻辑与C# record的编译器生成代码冲突导致的:

  • C# record编译时会自动生成隐藏的克隆构造函数,其中包含一个名为Original的参数,类型为当前record类型(此处为To),用于支持With方法的实例克隆功能。
  • AutoMapper的成员匹配逻辑会匹配名称相同的成员,无论其可见性(哪怕是编译器生成的隐藏成员)。它会误将源类的string? Original属性,与目标record的隐藏To Original参数关联映射。
  • 当源类的Original属性值为null时,AutoMapper尝试将null赋值给类型为To的参数,在内部反射处理过程中触发NullReferenceException。

两种规避场景的原理:

  • 修改源属性名:源属性名不再与record隐藏的Original参数重名,AutoMapper不会进行错误匹配。
  • 目标改为普通类:普通类没有编译器生成的隐藏Original克隆参数,AutoMapper只会映射双方显式定义的同名属性(此处只有BoolProp)。

解决方法

你可以通过以下任意一种方式解决问题:

  1. 修改源属性名:避免使用Original这类会与record隐藏成员冲突的名称。
  2. 显式指定映射成员:在AutoMapper配置中明确只映射目标record中存在的属性,避免AutoMapper尝试匹配隐藏成员:
var mapper = new MapperConfiguration(conf =>
{
    conf.CreateMap<From, To>()
        .ForMember(dest => dest.BoolProp, opt => opt.MapFrom(src => src.BoolProp));
}).CreateMapper();
  1. 忽略未匹配的成员:配置AutoMapper忽略目标中不存在的显式成员(间接避免匹配隐藏成员):
var mapper = new MapperConfiguration(conf =>
{
    conf.CreateMap<From, To>()
        .ForAllOtherMembers(opt => opt.Ignore());
}).CreateMapper();

内容的提问来源于stack exchange,提问作者Rowan Freeman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:16:13