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

AutoMapper映射DateTime无法转换为正确格式的问题排查

问题:AutoMapper自定义日期转换器未生效的解决方法

问题场景

我有两个API:一个接收POST请求并将数据存入数据库,数据映射至包含Id、DataReceived(多为JSON字符串)、Transfered属性的BaseModel;另一个API负责将DataReceived中的数据通过AutoMapper映射至第二个数据库的ModelOne。

配置的映射规则如下:

CreateMap<JToken, ModelOne>()

.ForAllMembers(opt =>
{
    opt.MapFrom(src => src.SelectToken(opt.DestinationMember.Name));
    opt.Condition((src, des, _, _, resolutionContext) =>
    {
        MemberInfo propDestination = opt.DestinationMember;
        string propName = propDestination.Name;

        // 尝试在这里用类型转换器处理数据
        if (Attribute.IsDefined(propDestination, typeof(CustomDateConvertAttribute)))
        {
            opt.ConvertUsing(new CustomDateTimeConverter(), src => src.SelectToken(propName).ToString());
        }

        // 所有成员都映射
        return true;
    });
});

自定义转换器实现:

public class CustomDateTimeConverter : IValueConverter<string, string>
{
    public string Convert(string source, ResolutionContext context)
    {
        DateTime dt;
        try
        {
            dt = DateTime.Parse(source);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            dt = DateTime.ParseExact(source, "dd/MM/yyyy h:mm:ss tt", CultureInfo.InvariantCulture);
        }

        return dt.Year + "-" + dt.Month + "-" + dt.Day + " " + dt.Hour + ":" + dt.Minute + ":" + dt.Second;
    }
}

但日期格式转换并未生效,请问如何解决?


问题原因

在Condition方法内调用opt.ConvertUsing是无效的:

  1. AutoMapper的配置是初始化阶段一次性完成的,运行时在Condition中修改映射规则不会被识别;
  2. Condition的作用是判断当前成员是否执行映射,而非用来动态添加转换逻辑;
  3. 原写法中ForAllMembers的逻辑会被每个成员重复执行,配置逻辑混乱。

解决方案

1. 修正映射配置逻辑

将转换器配置从Condition中移出,在配置阶段直接为带有CustomDateConvertAttribute的成员单独设置转换规则:

CreateMap<JToken, ModelOne>()
    // 为所有成员设置基础映射逻辑
    .ForAllMembers(opt => opt.MapFrom(src => src.SelectToken(opt.DestinationMember.Name)))
    // 针对带自定义属性的成员配置转换器
    .ForAllMembers(opt => 
    {
        if (Attribute.IsDefined(opt.DestinationMember, typeof(CustomDateConvertAttribute)))
        {
            opt.ConvertUsing(new CustomDateTimeConverter(), 
                src => src.SelectToken(opt.DestinationMember.Name)?.ToString());
        }
    });

2. 优化转换器实现

原转换器直接拼接字符串会导致格式不规范(如月份/日期小于10时无前置零),改用标准格式字符串输出,同时优化解析逻辑避免捕获通用异常:

public class CustomDateTimeConverter : IValueConverter<string, string>
{
    public string Convert(string source, ResolutionContext context)
    {
        if (string.IsNullOrWhiteSpace(source))
        {
            return string.Empty; // 或根据业务返回默认值
        }

        // 先尝试通用解析
        if (!DateTime.TryParse(source, out DateTime dt))
        {
            // 失败则尝试指定格式解析
            if (!DateTime.TryParseExact(source, "dd/MM/yyyy h:mm:ss tt", 
                CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
            {
                // 解析失败可抛出异常或返回默认值,根据业务需求调整
                throw new FormatException($"无法解析日期字符串:{source}");
            }
        }

        // 输出标准的yyyy-MM-dd HH:mm:ss格式
        return dt.ToString("yyyy-MM-dd HH:mm:ss");
    }
}

3. 验证属性标记

确保ModelOne中需要转换日期的属性已正确标记CustomDateConvertAttribute:

public class ModelOne
{
    [CustomDateConvert]
    public string CreateTime { get; set; }

    // 其他属性...
}

关键提示

AutoMapper的配置逻辑必须在初始化阶段完成,运行时动态修改配置不会生效。针对特殊成员的转换规则,应在配置阶段就明确区分,而非在映射执行的判断逻辑中临时添加。

内容的提问来源于stack exchange,提问作者Prosy A.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:43:20