如何通过自定义PersonRowMap:ClassMap<Person>生成指定CSV表头?
使用CsvHelper自定义ClassMap实现动态列CSV导出
实现思路
要生成指定格式的CSV,核心要完成两个操作:
- 固定映射
Name列 - 动态生成
SomeV 1至SomeV N的列,分别对应SomeValues列表中的每个元素
代码实现
定义自定义PersonRowMap时,需要先遍历所有数据获取SomeValues的最大长度,再基于这个长度动态构建映射规则(避免因不同实例列表长度不一致导致列缺失):
public class PersonRowMap : ClassMap<Person> { public PersonRowMap(int maxValuesCount) { // 映射Name列,设置表头 Map(p => p.Name).Name("Name"); // 动态生成SomeV 1到SomeV N的列 for (int i = 0; i < maxValuesCount; i++) { int index = i; // 捕获循环变量,避免闭包引用问题 Map(p => p.SomeValues) .Name($"SomeV {index + 1}") .Index(index + 1) // Name列占索引0,后续列从1开始 .ConvertUsing(row => { // 列表长度不足时返回空字符串,保证格式统一 return row.SomeValues != null && row.SomeValues.Count > index ? row.SomeValues[index].ToString() : string.Empty; }); } } }
使用方式
导出CSV时,先计算最大列表长度,再初始化自定义映射并配置CsvWriter:
var people = new List<Person> { new Person { Name = "Alpha", SomeValues = new List<decimal> { 1, 2, 3 } }, new Person { Name = "Beta", SomeValues = new List<decimal> { 4, 5 } } }; // 获取所有实例中SomeValues的最大长度 int maxCount = people.Max(p => p.SomeValues?.Count ?? 0); using var writer = new StringWriter(); using var csv = new CsvWriter(writer, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", // 设置分隔符为分号 ShouldQuote = _ => false // 不需要给字段加引号,匹配示例格式 }); // 注册自定义映射 csv.Context.RegisterClassMap(new PersonRowMap(maxCount)); // 写入表头和数据 csv.WriteHeader<Person>(); csv.NextRecord(); csv.WriteRecords(people); // 输出结果 Console.WriteLine(writer.ToString());
输出效果
运行后生成的CSV内容如下:
Name;SomeV 1;SomeV 2;SomeV 3; Alpha;1;2;3; Beta;4;5;;
内容的提问来源于stack exchange,提问作者Dmitry Popov
相关产品推荐
相关产品推荐

