如何使用AutoMapper转换可空decimal并保留两位小数?解决类型推断错误
问题描述
EntityOne和ModelOne中的Field1均为可空decimal类型,我希望在AutoMapper映射时将值保留两位小数。
原始映射代码:
CreateMap<EntityOne, ModelOne>() .ForPath(dest => dest.Field1, opt => opt.MapFrom(src => src.Field1))
尝试的映射代码:
CreateMap<EntityOne, ModelOne>() .ForPath(dest => dest.Field1, opt => opt.MapFrom(src => src.Field1.HasValue ? Math.Round((decimal)src.Field1, 2, MidpointRounding.AwayFromZero) : null))
遇到的错误:
The type arguments for method 'IPathConfigurationExpression<EntityOne, ModelOne, decimal?>.MapFrom(Expression<Func<EntityOne, TSourceMember>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
解决方案
问题根源是三元运算符两侧的类型无法被AutoMapper的泛型方法正确推断——Math.Round返回的是decimal,而null没有明确的可空decimal类型,导致泛型参数TSourceMember无法确定。以下是几种解决方式:
方式一:显式转换null为decimal?
将null强制转换为decimal?,让三元运算符两边类型统一:
CreateMap<EntityOne, ModelOne>() .ForPath(dest => dest.Field1, opt => opt.MapFrom(src => src.Field1.HasValue ? Math.Round((decimal)src.Field1, 2, MidpointRounding.AwayFromZero) : (decimal?)null));
方式二:使用default(decimal?)替代null
用default(decimal?)代替null,同样能明确返回类型:
CreateMap<EntityOne, ModelOne>() .ForPath(dest => dest.Field1, opt => opt.MapFrom(src => src.Field1.HasValue ? Math.Round((decimal)src.Field1, 2, MidpointRounding.AwayFromZero) : default(decimal?)));
方式三:使用自定义值转换器(适合多字段复用场景)
如果多个字段都需要保留两位小数的处理,建议封装自定义转换器,让映射代码更简洁:
// 定义转换器 public class RoundDecimalToTwoPlacesConverter : IValueConverter<decimal?, decimal?> { public decimal? Convert(decimal? source, ResolutionContext context) { return source.HasValue ? Math.Round(source.Value, 2, MidpointRounding.AwayFromZero) : null; } } // 配置映射 CreateMap<EntityOne, ModelOne>() .ForPath(dest => dest.Field1, opt => opt.ConvertUsing<RoundDecimalToTwoPlacesConverter>());
以上方法都能解决泛型类型推断错误,同时实现保留两位小数的映射需求。
内容的提问来源于stack exchange,提问作者CrazyLegs
相关产品推荐
相关产品推荐

