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

