CsvHelper CsvClassMap映射数组成员报Not a member access错误求助
CsvHelper映射数组字段报错解决方案
(更新版本)使用CsvHelper的CsvClassMap从CSV文件读取日期数据时,映射数组成员运行抛出错误:Not a member access Parameter name: expression。
原实现代码
主读取逻辑
void Main() { using (var reader = new StreamReader("path\\to\\file.csv")) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMap<LoanRecord>(); var records = csv.GetRecords<LoanRecord>(); } } public class LoanRecord : Model { public LoanRecord() { } public string[] LoanStart_DateTime = new string[2]; public string[] LoanEnd_DateTime = new string[2]; }
原映射类代码
public sealed class LoanMapper: CsvClassMap<LoanRecord> { public LoanMapper() { Map(m => m.LoanStart_DateTime[0]).Index(0); Map(m => m.LoanEnd_DateTime[0]).Index(1); Map(m => m.LoanStart_DateTime[1]).Index(2); Map(m => m.LoanEnd_DateTime[1]).Index(3); } }
对应CSV格式
LoanStart_DateTime1,LoanEnd_DateTime1,LoanStart_DateTime2,LoanEnd_DateTime2 01/12/2022 00:00,02/12/2022 00:00,23/05/2022 00:00,23/05/2022 03:00,
错误原因
- CsvHelper默认
Map方法的表达式解析逻辑仅支持直接映射类的公开属性/字段,不支持数组索引器这类带参数的成员访问写法,传入数组索引访问表达式时会直接抛出参数错误。 - 主逻辑存在笔误:
RegisterClassMap泛型参数传入的是实体类LoanRecord,而非自定义的映射类LoanMapper,映射规则本身不会生效。
解决方法
方法1:改用独立属性映射(推荐,实现最简单)
放弃数组存储结构,为每个CSV列定义独立的公开属性,完全符合CsvHelper默认映射规则:public class LoanRecord : Model { // 第一组日期字段,对应CSV前两列 public string LoanStart_DateTime1 { get; set; } public string LoanEnd_DateTime1 { get; set; } // 第二组日期字段,对应CSV后两列 public string LoanStart_DateTime2 { get; set; } public string LoanEnd_DateTime2 { get; set; } } public sealed class LoanMapper: CsvClassMap<LoanRecord> { public LoanMapper() { Map(m => m.LoanStart_DateTime1).Index(0); Map(m => m.LoanEnd_DateTime1).Index(1); Map(m => m.LoanStart_DateTime2).Index(2); Map(m => m.LoanEnd_DateTime2).Index(3); } }读取完成后如果需要数组结构,在业务代码中手动赋值即可,同时需要修正主逻辑中注册映射的笔误,将
RegisterClassMap<LoanRecord>()改为RegisterClassMap<LoanMapper>()。方法2:使用
ConvertUsing自定义赋值逻辑
如果必须保留数组字段结构,可以通过ConvertUsing方法手动从行数据中取值赋值,不需要走默认的成员表达式解析:public sealed class LoanMapper: CsvClassMap<LoanRecord> { public LoanMapper() { Map(m => m.LoanStart_DateTime).Convert(row => { return new string[2] { row.Row.GetField(0), row.Row.GetField(2) }; }); Map(m => m.LoanEnd_DateTime).Convert(row => { return new string[2] { row.Row.GetField(1), row.Row.GetField(3) }; }); } }该方法同样需要先修正注册映射类的笔误。
内容的提问来源于stack exchange,提问作者Knight
相关产品推荐
相关产品推荐

