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

CsvHelper自定义类型转换后仍抛出ReaderException问题求助

原因分析与解决方案

核心原因

你自定义的DecimalStringReplacer类型转换器,大概率在实现时最终返回的是字符串类型,而非decimal?类型。CsvHelper拿到转换器返回的字符串后,尝试直接赋值给decimal?类型的属性,自然会触发强制转换失败的异常。

比如错误的转换器实现:

public class DecimalStringReplacer : TypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        // 仅移除逗号,返回处理后的字符串而非decimal
        return text.Replace(",", "");
    }
}

可复现性

该行为完全可以复现:只要自定义TypeConverter返回的类型与目标属性类型(decimal?)不匹配,就会触发这个强制转换异常。

正确的转换器实现

修改ConvertFromString方法,在移除逗号后将字符串转换为decimal?类型返回:

public class DecimalStringReplacer : TypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if (string.IsNullOrWhiteSpace(text))
        {
            return null;
        }
        var cleanedText = text.Replace(",", "");
        return decimal.TryParse(cleanedText, out var result) ? result : null;
    }

    // 可选:实现写入CSV时的反向转换逻辑
    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value is decimal? decValue && decValue.HasValue)
        {
            return decValue.Value.ToString("N2");
        }
        return string.Empty;
    }
}

无需自定义转换器的替代方案

其实不用自定义转换器也能解决问题:de-CH文化的千位分隔符是单引号'、小数点是逗号,,但你的CSV用的是英文格式的千位分隔符,和小数点.。直接指定匹配CSV格式的文化信息即可:

public class MyFileMap : ClassMap<MyFile>
{
    public MyFileMap()
    {
        Map(x => x.MyField).Name("My Field")
            .TypeConverterOption.CultureInfo(CultureInfo.GetCultureInfo("en-US"))
            .TypeConverterOption.NumberStyles(NumberStyles.Number);
    }
}

这样内置转换器就能直接解析"120,000.00"为decimal?,无需额外自定义逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:25:57