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

AutoMapper升级后GetValueOrDefault行为异常,此情况是否符合预期?

AutoMapper 11+版本中GetValueOrDefault(DateTime.Today)映射失效问题

复现场景

最小复现代码

using AutoMapper;

var a = new ClassA { DueDate = null };
var config = new MapperConfiguration(c => c.AddProfile<Prof>());
var mapper = config.CreateMapper();
var b = mapper.Map<ClassA, ClassB>(a);
Console.WriteLine(b);

public class ClassA
{
    public DateTime? DueDate { get; set; }

    public override string ToString() => $"{{ {nameof(DueDate)}: {DueDate} }}";
}

public class ClassB
{
    public DateTime ExpirationDate { get; set; }

    public override string ToString() => $"{{ {nameof(ExpirationDate)}: {ExpirationDate} }}";
}

public class Prof : Profile
{
    public Prof()
    {
        CreateMap<ClassA, ClassB>()
            .ForMember(b => b.ExpirationDate, cf => cf.MapFrom(a => a.DueDate.GetValueOrDefault(DateTime.Today)));
    }
}

项目配置

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AutoMapper" Version="11.0.2-alpha.0.12" />
  </ItemGroup>

</Project>

版本差异

  • AutoMapper 10.0.0:输出符合预期 { ExpirationDate: 18/8/2022 00:00:00 }
  • AutoMapper 11.0.1/11.0.2-alpha:输出异常 { ExpirationDate: 1/1/0001 00:00:00 }

结论

这个行为是AutoMapper 11.0.1及以上版本的行为变更,属于版本升级后的预期调整(或无意的破坏性变更),并非Bug,但需要调整映射逻辑适配新的解析规则。

原因分析

在AutoMapper 10.x版本中,Nullable<T>.GetValueOrDefault(T defaultValue)的表达式会被完整解析,当源值为null时,会正确执行传入的defaultValue计算逻辑(即DateTime.Today)。

升级到11.x版本后,AutoMapper对表达式树的解析逻辑发生变化:它没有正确捕获GetValueOrDefault的参数,而是默认 fallback 到无参的GetValueOrDefault()实现,返回default(DateTime)也就是DateTime.Min(1/1/0001)。

解决办法

方法1:使用空合并运算符??替代GetValueOrDefault

空合并运算符的逻辑会被AutoMapper正确解析,完全符合预期:

public class Prof : Profile
{
    public Prof()
    {
        CreateMap<ClassA, ClassB>()
            .ForMember(b => b.ExpirationDate, cf => cf.MapFrom(a => a.DueDate ?? DateTime.Today));
    }
}

方法2:使用ResolveUsing显式指定解析逻辑

如果需要保留GetValueOrDefault的写法,可以改用ResolveUsing,确保映射逻辑被完整执行:

public class Prof : Profile
{
    public Prof()
    {
        CreateMap<ClassA, ClassB>()
            .ForMember(b => b.ExpirationDate, cf => cf.ResolveUsing(a => a.DueDate.GetValueOrDefault(DateTime.Today)));
    }
}

修改后,无论在AutoMapper 10.0.0还是11.x版本中,当DueDate为null时,都会正确返回DateTime.Today的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:48:24