如何使用 CSVHelper 编写非平面类的标题?

Posted

技术标签:

【中文标题】如何使用 CSVHelper 编写非平面类的标题?【英文标题】:How write header of not flat class using CSVHelper? 【发布时间】:2015-03-20 13:48:21 【问题描述】:
public class Class1

    [CsvField(Name = "Field1")]
    public int Field1  get; set; 

    [CsvField(Name = "Field2")]
    public int Field2  get; set; 

    [CsvField(Ignore = true)]
    public Class2 Class2  get; set; 

    [CsvField(Ignore = true)]
    public Class3 Class3  get; set; 


public class Class2

    [CsvField(Name = "Field3")]
    public int Field3  get; set; 

    [CsvField(Name = "Field4")]
    public int Field4  get; set; 


public class Class3

    [CsvField(Name = "Field5")]
    public int Field5  get; set; 

    [CsvField(Name = "Field6")]
    public int Field6  get; set; 

我正在使用CSVHelper 将数据写入 CSV 文件。 我需要用这样的标题写 Class1:

字段1、字段2、字段3、字段4、字段5、字段6

我该怎么做?

【问题讨论】:

您可以添加额外的公共属性来访问 Class2 和 Class3 的方法。然后将属性应用于这些属性。 【参考方案1】:

这是一个老问题,所以您可能已经有了答案。你有几个选择。

选项 1(我知道可行) Documentation

您只需要手动写出 CSV 的内容,下面是一些可以帮助您入门的代码,但您需要根据对象内容的存储方式进行修改。

using (var stream = new MemoryStream())

    using (var streamWriter = new StreamWriter(stream))
    using (var csv = new CsvWriter(streamWriter))
    
        // Write out header
        csv.WriteField("Field1");
        csv.WriteField("Field2");
        csv.WriteField("Field3");
        csv.WriteField("Field4");
        csv.WriteField("Field5");
        csv.WriteField("Field6");

        // Write out end line
        csv.NextRecord();

        //Pseudocode
        foreach (var item in Class1Collection)
        
            csv.WriteField(item.Field1);
            csv.WriteField(item.Field2);
            csv.WriteField(item.Class2.Field3);
            csv.WriteField(item.Class2.Field4);
            csv.WriteField(item.Class3.Field5);
            csv.WriteField(item.Class3.Field6);

            // Write out end line
            csv.NextRecord();
        
    

选项2(用过,但不是这样)Documentation

您的第二个选项是编写一个自定义CSVMap,告诉 CSVWriter 如何处理嵌套类。我不知道如何处理这个名字,所以你可能需要解决这个问题。

public sealed class Class1CSVMap : CsvClassMap<RemittanceFormModel>

    public Class1CSVMap()
    
        Map(m => m.Field1).Name("Field1");
        Map(m => m.Field2).Name("Field2");
        Map(m => m.Class2).Name("Field3,Field4").TypeConverter<Class2Converter>();
        Map(m => m.Class3).Name("Field5,Field6").TypeConverter<Class3Converter>();
    

然后你就有了你的转换器,一个用于 Class2,一个用于 Class3

public class Class2Converter : DefaultTypeConverter

    public override string ConvertToString(TypeConverterOptions options, object model)
    
        var result = string.Empty;

        var classObject = model as Class2;

        if (classObject != null)
        
            result = string.Format("0,1", classObject.Field3, classObject.Field4);
        

        return result;
    

选项 3(从未使用过) Documentation

你可以做一个内联转换器而不是创建一个单独的类。我从未尝试过,但它应该可以工作。

public sealed class Class1CSVMap : CsvClassMap<Class1>

    public Class1CSVMap()
    
            Map(m => m.Field1).Name("Field1");
            Map(m => m.Field2).Name("Field2");
            Map(m => m.Class2).Name("Field3,Field4").ConvertUsing(row =>  string.Format("0,1", row.Field3, row.Field4); );
            Map(m => m.Class3).Name("Field5,Field6").ConvertUsing(row =>  string.Format("0,1", row.Field5, row.Field6); );
    

【讨论】:

以上是关于如何使用 CSVHelper 编写非平面类的标题?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 EnumConverter 与 CsvHelper 一起使用

C# CSVhelper 无法使用自定义映射编写

将 CsvHelper 自定义转换器应用于一组类的所有字符串属性

编写时在 CsvHelper 中转换或过滤成员

使用 CSVhelper 将单个列更新为先前编写的 CSV 文件。我有 Java 代码,但无法将其翻译成 C#

使用 CsvHelper 将 CSV 中的所有值读入列表