【问题标题】:Can we use both Index and Name attributes for our properties with CsvHelper?我们可以在 CsvHelper 的属性中同时使用 Index 和 Name 属性吗?
【发布时间】:2022-01-23 02:58:12
【问题描述】:

我是使用CsvHelper API 编写 CSV 文件的新手。我已经阅读了Getting Started 帮助主题。

我需要创建一个只定义了标题的空 CSV 文件。这样用户就可以从这个模板文件开始并填充数据。

我知道如何手动创建文本文件并自己手动完成。但是,由于我的课程具有读取 CSV 的属性,我想知道是否可以利用它来做相反的事情?

我在WriteHeader 看到了一个例子,所以我想出了:

public void CreateEmptyHistoryFile(string path)
{
    using (var writer = new StreamWriter(path))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
        csv.WriteHeader<GenericHistory>();
    }
}    

但如果可以将 both 这些属性添加到我的属性中,我找不到它的文档:

[Index(1)]
[Name(“xxx”)]
Public string Yyy …

链接的文章说:

还记得我们不能依赖 .NET 中的属性顺序吗?如果我们正在编写一个具有标题的类,那没关系,只要我们稍后使用标题进行读取即可。 如果我们想在 CSV 文件中定位标题,我们需要指定一个索引来保证它的顺序。建议在写入时始终设置索引。

  • 当我使用 name 属性阅读时。
  • 当我编写带有标题的空文件时,我想按顺序(只是为了清楚起见)来呈现它们。

有意义吗?我们可以混合使用这两个属性吗?


更新

我想知道关于属性顺序的建议是否过时了?

我刚刚运行了我的代码,输出按写入顺序排列(我没有添加 Index 属性)。


更新

我的班级有 82 个属性,我尝试为每个属性添加一个 Index 属性。当我尝试阅读时,我遇到了一个异常:

  <LogEntry Date="2022-01-22 18:38:03" Severity="Exception" Source="MSAToolsLibrary.Importer.Importer.ImportHistoryFromGeneric" ThreadId="1">
    <Exception Type="CsvHelper.TypeConversion.TypeConverterException" Source="CsvHelper.TypeConversion.DefaultTypeConverter.ConvertFromString">
      <Message>The conversion cannot be performed.
    Text: 'Andrew Truckle'
    MemberType: System.Int32
    TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'
IReader state:
   ColumnCount: 0
   CurrentIndex: 4
   HeaderRecord:
["Week","MidweekMeeting","WeekendMeeting","NumClasses","Host","Cohost","Chairman","AuxCounsellor1","AuxCounsellor2","PrayerOpen","Treasures_Name","Treasures_Theme","Treasures_Method","Gems_Name","Teaching","Teaching_Class1_Name","Teaching_Class2_Name","Teaching_Class3_Name","BibleReading_Study","StudentItem1_Study","StudentItem2_Study","StudentItem3_Study","StudentItem4_Study","StudentItem1_Description","StudentItem2_Description","StudentItem3_Description","StudentItem4_Description","BibleReading_Class1_Name","BibleReading_Class2_Name","BibleReading_Class3_Name","StudentItem1_Class1_Name","StudentItem1_Class1_Assistant","StudentItem2_Class1_Name","StudentItem2_Class1_Assistant","StudentItem3_Class1_Name","StudentItem3_Class1_Assistant","StudentItem4_Class1_Name","StudentItem4_Class1_Assistant","StudentItem1_Class2_Name","StudentItem1_Class2_Assistant","StudentItem2_Class2_Name","StudentItem2_Class2_Assistant","StudentItem3_Class2_Name","StudentItem3_Class2_Assistant","StudentItem4_Class2_Name","StudentItem4_Class2_Assistant","StudentItem1_Class3_Name","StudentItem1_Class3_Assistant","StudentItem2_Class3_Name","StudentItem2_Class3_Assistant","StudentItem3_Class3_Name","StudentItem3_Class3_Assistant","StudentItem4_Class3_Name","StudentItem4_Class3_Assistant","Living1_Name","Living1_Theme","Living1_Method","Living2_Name","Living2_Theme","Living2_Method","Living3_Name","Living3_Theme","Living3_Method","CBS_Conductor","CBS_Reader","PrayerClose","Weekend_Host","Weekend_Cohost","Weekend_Chairman","Weekend_PrayerOpen","Weekend_PT_Speaker","Weekend_PT_Theme","Weekend_PT_Number","Weekend_PT_Hospitality","Weekend_PT_Interpreter","Weekend_AT1_Name","Weekend_AT2_Name","Weekend_WT_Conductor","Weekend_WT_Reader","Weekend_WT_BibleVersesReader","Weekend_PrayerClose","Weekend_Misc"]
IParser state:
   ByteCount: 0
   CharCount: 2289
   Row: 2
   RawRow: 2
   Count: 82
   RawRecord:
27/01/2020,Y,Y,1,...

</Message>
      <StackTrace>   at CsvHelper.TypeConversion.DefaultTypeConverter.ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData)
   at CsvHelper.TypeConversion.Int32Converter.ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData)
   at lambda_method(Closure )
   at CsvHelper.Expressions.RecordCreator.Create[T]()
   at CsvHelper.CsvReader.&lt;GetRecords&gt;d__87`1.MoveNext()
   at MSAToolsLibrary.Importer.Importer.ImportHistoryFromGeneric()</StackTrace>
    </Exception>
  </LogEntry>

出于隐私原因,我已删除数据中的姓名。我注意到它引用当前索引 4 并执行整数转换。如您所见,该值为1。在阅读课上:

[Index(4)]
public int NumClasses { get => HistoryWeek.NumClasses; set => HistoryWeek.NumClasses = value; }

正如我所说,如果我删除所有 [Index(..)] 我的阅读代码仍然有效。但是,如果我重新引入所有索引值,则会失败。

【问题讨论】:

    标签: c# csvhelper


    【解决方案1】:

    我通常发现它的顺序与在您的类中声明的属性的顺序相同。但是,如果您想确定它们是按特定顺序排列的,我会同时使用它们。

    Type.GetProperties Method

    GetProperties 方法不按特定顺序返回属性,例如字母顺序或声明顺序。您的代码不得依赖于返回属性的顺序,因为该顺序会有所不同。

    您可以试试这个例子,看看NameIndex 属性在使用CsvWriter 时都会起作用。

    void Main()
    {
        using (var csv = new CsvWriter(Console.Out, CultureInfo.InvariantCulture))
        {
            csv.WriteHeader<Foo>();
        }
    }
    
    public class Foo
    {
        [Name("Identity")]
        [Index(1)]
        public int Id { get; set; }
        [Name("FirstName")]
        [Index(0)]
        public string Name { get; set; }
    }
    

    【讨论】:

    • 奇怪。我在类中有 82 个属性,我从 1 开始按顺序编号。然而,当我尝试使用我的“阅读”代码时,我遇到了一个异常。当我删除所有 Index 属性时,我的相同阅读代码有效。
    • 尝试使用 0 索引开始。
    • 我更新了我的答案以使用 0 索引。
    • 现在工作正常。
    猜你喜欢
    • 2011-04-12
    • 2013-01-07
    • 2022-01-01
    • 2022-07-01
    • 1970-01-01
    • 2013-04-03
    • 2011-08-06
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多