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
相关产品推荐
相关产品推荐

