Automapper 11.0中Nullable DateTime映射扩展方法未触发问题求助
AutoMapper 11.0 中
DateTime?映射string时null值不触发扩展方法的问题解决 问题场景
在.NET 6环境搭配AutoMapper 11.0时,将可空DateTime类型(DateTime?)映射到字符串时,若源值为null,自定义扩展方法ToCommon()不会被执行,目标字段直接返回null,不符合预期的"something"结果。但相同代码在AutoMapper 10.0中可正常触发扩展方法并返回预期值。
复现代码
void Main() { var config = new MapperConfiguration(cfg => { cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date.ToCommon())); }); IMapper mapper = config.CreateMapper(); var source = new Source { Date = null }; var destination = mapper.Map<Destination>(source); Console.WriteLine(destination.Date); } public static class Temp { public static string ToCommon(this DateTime? dateTime) { if (dateTime is null) return "something"; return dateTime.Value.ToString("yyyy/MM/dd"); } } public class Source { public DateTime? Date { get; set; } } public class Destination { public string Date { get; set; } }
原因分析
AutoMapper 11.0对null值的处理逻辑做了变更:当源成员为null时,框架默认会跳过映射表达式的执行,直接将目标字段设为null,不会调用你的扩展方法。这是新版本中优化null检测带来的行为变化,和10.0的处理逻辑不同。
解决方案
方案1:显式调用静态方法(绕过扩展方法语法的null检测)
扩展方法本质是静态方法,直接通过静态类调用,避免AutoMapper的null优化跳过执行:
cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Date, opt => opt.MapFrom(src => Temp.ToCommon(src.Date)));
也可以给扩展方法调用加括号,强制表达式执行:
cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Date, opt => opt.MapFrom(src => (src.Date).ToCommon()));
方案2:使用自定义类型转换器(推荐,适合复用场景)
创建专门的类型转换器处理DateTime?到string的转换,确保无论源是否为null都能触发逻辑:
public class DateTimeNullableToStringConverter : ITypeConverter<DateTime?, string> { public string Convert(DateTime? source, string destination, ResolutionContext context) { return source?.ToString("yyyy/MM/dd") ?? "something"; } }
然后在映射配置中注册转换器:
var config = new MapperConfiguration(cfg => { cfg.CreateMap<DateTime?, string>().ConvertUsing<DateTimeNullableToStringConverter>(); cfg.CreateMap<Source, Destination>(); });
方案3:全局配置关闭null跳过(谨慎使用)
如果需要全局禁用AutoMapper的null值跳过行为,可以在配置中添加:
var config = new MapperConfiguration(cfg => { cfg.ForAllMembers(opt => opt.Condition((src, dest, srcMember) => true)); cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date.ToCommon())); });
该配置会让所有成员无论源是否为null都执行映射表达式,但可能影响其他映射的性能或逻辑,按需使用。
验证效果
修改后重新运行代码,当源Date为null时,目标Date字段会正确返回"something",符合预期。
内容的提问来源于stack exchange,提问作者lin kuanfu
相关产品推荐
相关产品推荐

