CSVHelper 不硬编码索引、给动态指定ClassMap传int[]参数的实现方法
解决方案
你可以通过Activator.CreateInstance传入构造参数创建映射类实例,再调用CsvHelper提供的接收ClassMap实例的注册重载实现需求,无需硬编码映射类类型。
修改后的核心代码
首先替换WriteRecords方法中注册映射的代码段:
public static void WriteRecords(string fileSpecification, string[] headerRow, Type classMapType, int[] indexes, IEnumerable<object> records) { using (StreamWriter streamWriter = new StreamWriter(fileSpecification)) using (CsvWriter csvWriter = new CsvWriter(streamWriter, noHeaderConfiguration)) { // 可选:提前校验映射类合法性,避免运行时报错 if (!typeof(ClassMap).IsAssignableFrom(classMapType)) { throw new ArgumentException($"传入的类型{nameof(classMapType)}不是合法的ClassMap子类", nameof(classMapType)); } var targetConstructor = classMapType.GetConstructor(new[] { typeof(int[]) }); if (targetConstructor == null) { throw new ArgumentException($"映射类{classMapType.Name}不存在接收int[]参数的公共构造函数", nameof(classMapType)); } // 动态创建映射类实例,传入indexes作为构造参数 var classMapInstance = (ClassMap)Activator.CreateInstance(classMapType, new object[] { indexes }); // 调用接收实例的重载注册映射 csvWriter.Context.RegisterClassMap(classMapInstance); WriteHeader(headerRow, csvWriter); csvWriter.NextRecord(); csvWriter.WriteRecords(records); } }
实现原理
- 你之前报错的原因是调用了
RegisterClassMap(Type type)重载,该方法会默认使用无参构造函数实例化映射类,而你的自定义映射类没有无参构造,自然抛出异常。 Activator.CreateInstance支持传入构造参数,注意需要把参数按顺序放到object[]中传入,避免int数组的每个元素被识别为单独的构造参数,即可正确创建带参构造的类实例。- 所有自定义映射类都继承自
ClassMap基类,将实例强转为ClassMap后,即可调用RegisterClassMap(ClassMap map)重载完成注册,不需要知道具体的子类类型。
内容的提问来源于stack exchange,提问作者Oscar T
相关产品推荐
相关产品推荐

