如何修改此代码以与 CsvHelper/CsvReader 一起使用,从而使 class 的处理效率更高?

How can this code be modified to work with CsvHelper/CsvReader to make the class more efficient for processing?

这个问题是这个问题的衍生问题 ()。在对该问题的评论中提出了这一点:

The refactoring needs to be done in a different place. It's not your function that sucks, it's the definition of CLMExplorerHistory.

The internal data structure does not need to represent the structure of the CSV file in a 1:1 fashion. Just make sure you can read and write in a compatible way.

I think that you're attempting to use the csv data structure directly rather than look at possible areas of duplication that would indicate the obvious place for implementing a class type in order to allow for code reuse. Could you post up a snippet of example data for your CSV file to indicate your starting point?


在这些评论的后端,这里是示例 CSV 数据的片段:

Date,Status,Weekly Bible Reading,Song1 #,Song1 Title,Song1 Scripture,Song2 #,Song2 Title,Song2 Scripture,Song3 #,Song3 Title,Song3 Scripture,Meeting?,CO Visit,Cancel Reason,# Classes,Chairman,PrayerOpen,PrayerClose,TreasuresTalk,TreasuresTalk_Theme,TreasuresDigging,BibleReading_A,BibleReading_Study_A,BibleReading_B,BibleReading_Study_B,BibleReading_C,BibleReading_Study_C,BibleReading_Source,Apply1_Description,Apply2_Description,Apply3_Description,Apply4_Description,Apply1_A,Apply1_Asst_A,Apply1_Study_A,Apply2_A,Apply2_Asst_A,Apply2_Study_A,Apply3_A,Apply3_Asst_A,Apply3_Study_A,Apply4_A,Apply4_Asst_A,Apply4_Study_A,Apply1_B,Apply1_Asst_B,Apply1_Study_B,Apply2_B,Apply2_Asst_B,Apply2_Study_B,Apply3_B,Apply3_Asst_B,Apply3_Study_B,Apply4_B,Apply4_Asst_B,Apply4_Study_B,Apply1_C,Apply1_Asst_C,Apply1_Study_C,Apply2_C,Apply2_Asst_C,Apply2_Study_C,Apply3_C,Apply3_Asst_C,Apply3_Study_C,Apply4_C,Apply4_Asst_C,Apply4_Study_C,LivingPart1,LivingPart1_Theme,LivingPart1_Length,LivingPart2,LivingPart2_Theme,LivingPart2_Length,CBS,CBS_Source,CBS_Read,Audience B,Audience C,AuxCounselor B,AuxCounselor C
01/03/2021,Registrato e completo,NUMERI 7-8,4,“Geova è il mio Pastore”,Salmo 23,54,“Questa è la via”,"Isaia 30:20, 21",127,Che tipo di persona sono?,2 Pietro 3:11,Y,N,,1,Italo De Gaeta,xxx,xxx,xxx,“L’accampamento d’Israele: lezioni utili”,xxx,xxx,5,,,,,Nu 7:1-17,Commemorazione,Visita ulteriore,Visita ulteriore,Visita ulteriore,xxx,xxx,11,xxx,xxx,6,xxx,xxx,12,xxx,xxx,17,,,,,,,,,,,,,,,,,,,,,,,,,xxx,Risultati raggiunti dall’organizzazione,(5 min),xxx,Bisogni locali,(10 min),xxx,"rr cap. 5 parr. 17-22, riquadro 5A",xxx,,,,

我使用 CsvReader class 将其读入 CLMExplorerHistory 对象。 class 定义如下:

public class CLMExplorerHistory
{
    [Format("dd/MM/yyyy")]
    [Name("Date")]
    public DateTime Date { get; set; }

    [BooleanFalseValues(new string[] { "N", "n" })]
    [BooleanTrueValues(new string[] { "Y", "y" })]
    [Name("Meeting?")]
    public bool Meeting { get; set; }

    [Name("# Classes")]
    public int Classes { get; set; }

    [Name("Chairman")]
    public string Chairman { get; set; }

    [Name("AuxCounselor B")]
    public string AuxCounsellor1 { get; set; }

    [Name("AuxCounselor C")]
    public string AuxCounsellor2 { get; set; }

    [Name("PrayerOpen")]
    public string PrayerOpen { get; set; }

    [Name("PrayerClose")]
    public string PrayerClose { get; set; }

    [Name("CBS")]
    public string CBSConductor { get; set; }

    [Name("CBS_Read")]
    public string CBSReader { get; set; }

    [Name("TreasuresTalk")]
    public string TreasuresTalkName { get; set; }

    [Name("TreasuresTalk_Theme")]
    public string TreasuresTalkTheme { get; set; }

    [Name("TreasuresDigging")]
    public string SpiritualGemsName { get; set; }

    [Name("LivingPart1")]
    public string LivingPart1Name { get; set; }

    [Name("LivingPart1_Theme")]
    public string LivingPart1Theme { get; set; }

    [Name("LivingPart2")]
    public string LivingPart2Name { get; set; }

    [Name("LivingPart2_Theme")]
    public string LivingPart2Theme { get; set; }

    [Name("BibleReading_A")]
    public string BibleReadingClass1Name { get; set; }

    [Name("BibleReading_B")]
    public string BibleReadingClass2Name { get; set; }

    [Name("BibleReading_C")]
    public string BibleReadingClass3Name { get; set; }

    [Name("BibleReading_Study_A")]
    public string BibleReadingStudy { get; set; }

    [Name("Apply1_Description")]
    public string StudentItem1Description { get; set; }

    [Name("Apply2_Description")]
    public string StudentItem2Description { get; set; }

    [Name("Apply3_Description")]
    public string StudentItem3Description { get; set; }

    [Name("Apply4_Description")]
    public string StudentItem4Description { get; set; }

    [Name("Apply1_A")]
    public string StudentItem1Class1StudentName { get; set; }

    [Name("Apply1_B")]
    public string StudentItem1Class2StudentName { get; set; }

    [Name("Apply1_C")]
    public string StudentItem1Class3StudentName { get; set; }

    [Name("Apply1_Asst_A")]
    public string StudentItem1Class1AssistantName { get; set; }

    [Name("Apply1_Asst_B")]
    public string StudentItem1Class2AssistantName { get; set; }

    [Name("Apply1_Asst_C")]
    public string StudentItem1Class3AssistantName { get; set; }

    [Name("Apply2_A")]
    public string StudentItem2Class1StudentName { get; set; }

    [Name("Apply2_B")]
    public string StudentItem2Class2StudentName { get; set; }

    [Name("Apply2_C")]
    public string StudentItem2Class3StudentName { get; set; }

    [Name("Apply2_Asst_A")]
    public string StudentItem2Class1AssistantName { get; set; }

    [Name("Apply2_Asst_B")]
    public string StudentItem2Class2AssistantName { get; set; }

    [Name("Apply2_Asst_C")]
    public string StudentItem2Class3AssistantName { get; set; }

    [Name("Apply3_A")]
    public string StudentItem3Class1StudentName { get; set; }

    [Name("Apply3_B")]
    public string StudentItem3Class2StudentName { get; set; }

    [Name("Apply3_C")]
    public string StudentItem3Class3StudentName { get; set; }

    [Name("Apply3_Asst_A")]
    public string StudentItem3Class1AssistantName { get; set; }

    [Name("Apply3_Asst_B")]
    public string StudentItem3Class2AssistantName { get; set; }

    [Name("Apply3_Asst_C")]
    public string StudentItem3Class3AssistantName { get; set; }

    [Name("Apply4_A")]
    public string StudentItem4Class1StudentName { get; set; }

    [Name("Apply4_B")]
    public string StudentItem4Class2StudentName { get; set; }

    [Name("Apply4_C")]
    public string StudentItem4Class3StudentName { get; set; }

    [Name("Apply4_Asst_A")]
    public string StudentItem4Class1AssistantName { get; set; }

    [Name("Apply4_Asst_B")]
    public string StudentItem4Class2AssistantName { get; set; }

    [Name("Apply4_Asst_C")]
    public string StudentItem4Class3AssistantName { get; set; }

    [Name("Apply1_Study_A")]
    public string StudentItem1Study { get; set; }

    [Name("Apply2_Study_A")]
    public string StudentItem2Study { get; set; }

    [Name("Apply3_Study_A")]
    public string StudentItem3Study { get; set; }

    [Name("Apply4_Study_A")]
    public string StudentItem4Study { get; set; }
}

我在 CSV 文件中这样读:

using (var reader = new StreamReader(_calendarDBPath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    var records = csv.GetRecords<CLMExplorerHistory>();

    foreach (var record in records)
    {
        ...

目前 CSV 记录被读入此 public 属性列表。我想知道它是否可以直接将字段读入更复杂的对象?

具体来说,# Classes 字段的值为 1、2 或 3。对于这些 classes(不是 C# classes - 认为 school)有类似的数据。

每个 class 有 4 个项目,每个 class 的描述/研究相同。所以这些 CSV 字段很常见:

[Name("Apply1_Description")]
[Name("Apply2_Description")]
[Name("Apply3_Description")]
[Name("Apply4_Description")]

[Name("BibleReading_Study_A")]
[Name("Apply1_Study_A")]
[Name("Apply2_Study_A")]
[Name("Apply3_Study_A")]
[Name("Apply4_Study_A")]

但其余部分特定于 3 Classes(学校):

[Name("BibleReading_A")]
[Name("Apply1_A")]
[Name("Apply1_Asst_A")]
[Name("Apply2_A")]
[Name("Apply2_Asst_A")]
[Name("Apply3_A")]
[Name("Apply3_Asst_A")]
[Name("Apply4_A")]
[Name("Apply4_Asst_A")]
[Name("BibleReading_B")]
[Name("Apply1_B")]
[Name("Apply1_Asst_B")]
[Name("Apply2_B")]
[Name("Apply2_Asst_B")]
[Name("Apply3_B")]
[Name("Apply3_Asst_B")]
[Name("Apply4_B")]
[Name("Apply4_Asst_B")]
[Name("BibleReading_C")]
[Name("Apply1_C")]
[Name("Apply1_Asst_C")]
[Name("Apply2_C")]
[Name("Apply2_Asst_C")]
[Name("Apply3_C")]
[Name("Apply3_Asst_C")]
[Name("Apply4_C")]
[Name("Apply4_Asst_C")]

3 Classes 不能由 Lists 中的 3 个“StudentClass”对象表示。像

StudentClasses
    NumClasses
    Item1Desc
    Item2Desc
    Item3Desc
    Item4Desc
    BibleReadingStudy
    Item1Study
    Item2Study
    Item3Study
    Item4Study
    List<StudentClass>
           BibleReading
           Item1Student
           Item1Assistant
           Item2Student
           Item2Assistant
           Item3Student
           Item3Assistant
           Item4Student
           Item4Assistant

以上内容来自:

StudentClasses
    NumClasses:        # Classes
    Item1Desc:         Apply1_Description
    Item2Desc:         Apply2_Description
    Item3Desc:         Apply3_Description
    Item4Desc:         Apply4_Description
    BibleReadingStudy: BibleReading_Study_A
    Item1Study:        Apply1_Study_A
    Item2Study:        Apply2_Study_A
    Item3Study:        Apply3_Study_A
    Item4Study:        Apply4_Study_A
    List<StudentClass>
           BibleReading    BibleReading_A|B|C
           Item1Student    Apply1_A|B|C
           Item1Assistant  Apply1_Asst_A|B|C
           Item2Student    Apply2_A|B|C
           Item2Assistant  Apply2_Asst_A|B|C
           Item3Student    Apply3_A|B|C
           Item3Assistant  Apply3_Asst_A|B|C
           Item4Student    Apply4_A|B|C
           Item5Assistant  Apply4_Asst_A|B|C

现在您知道了字段与建议对象之间的映射。显然我可以自己创建 C# class 并且我可以手动将字段传输到这样的结构中。但是 CvsReader 有能力像这样直接读入 class 吗?而不是一大串属性?

But does CvsReader have the ability to directly read into a class like this? Rather than one big list of properties?

我会说“是”,虽然我不能 100% 确定您最终希望创建什么,但是您可以通过 属性的作用.我举一个简单的例子。

假设我们有一个 CSV,其中列出了商店和需要从每个商店购买的 3 种产品

Shop,Product1,P1Price,Product2,P2Price,Product3,P3Price
Walmart,Eggs,1,Milk,2,Bread,3
BestBuy,PC,4,iPad,5,iPhone,6

你可以让你的 class 持有道具:

class ShopLine
{
  string Shop {get;set;}
  string Product1 {get;set;}
  string Product2 {get;set;}
  string Product3 {get;set;}
  int P1Price {get;set;}
  int P2Price {get;set;}
  int P3Price {get;set;}
}

但是没有人拿枪指着你的头说数据存储必须是这样的。你可以:

class Product
{
  string Name {get;set;}
  int Price {get;set;}
}

class ShopLineTrick
{
  string Shop {get;set;}
  string Product1 {get => products[0].Name; set => products[0].Name= value;}
  string Product2 {get => products[1].Name; set => products[1].Name= value;}
  string Product3 {get => products[2].Name; set => products[2].Name= value;}
  int P1Price {get => products[0].Price; set => products[0].Price = value;}
  int P2Price {get => products[1].Price; set => products[1].Price = value;}
  int P3Price {get => products[2].Price; set => products[2].Price = value;}

  List<Product> products;

  ShopLineTrick(){
     //precreate 3 products
     products = Enumerable.Range(1,3).Select(x => new Product()).ToList();
  }
}

在操作结束时,您有一些 ShopLineTrick 集合,每个集合都包含一些已构建的产品层次结构;产品是“来自其他地方的可重用 class”,因此此操作就像一个解析和映射。以前用于接收文件中数据的 POCO 已经成为一种能够从其他地方构建更小、可重用 classes 的层次结构的设备。您可以使用 LINQ 查询以获取它们,例如

shopLines.SelectMany(sl => sl.Products). // a straight list of every product

我已经使用替代示例进行了解释,因为我还不太了解您希望使用您拥有的数据实现什么:我正在描述替代数据存储,因此您可以将其应用于进一步目标。例如,对于最近的一个项目,我必须在某个时间点存储 属性 的每个版本,然后让我无法控制的进程改变对象的某些属性,然后检查发生了什么变化。这在循环中很容易做到,10 个属性中的每一个都使用一个对象 [10] 进行存储。在某个时间点,我会克隆数组,让进程更改内容,然后在当前中查找与克隆副本不同的数组条目。通过循环数组

,使用数组支持属性使得检查(甚至 reset/accept 更改)变得微不足道

唯一需要注意的是某些类型的 CsvH 读取,它 重用 您传递的对象,因此如果您是做一个异步读取只是要知道它可以读取文件的所有行并且你最终只会得到最后一个的数据(你需要提取产品列表,并在每次循环传递时更新它以防止覆盖)

此答案基于已接受答案中的原则。我觉得我会把它添加为对我的特定场景的扩展解释。它可能会对其他人有所帮助。


第 1 步

我设计了一组 classes 来表示一个会议周:

public class MSAHistoryItemTalk
{
    public string Name { get; set; }
    public string Theme { get; set; }
    public string Method { get; set; }
}
public class MSAHistoryItemStudent
{
    public string Name { get; set; }
    public string Assistant { get; set; }
    public string Type { get; set; }
    public string Study { get; set; }
}

public class MSAHistoryWeek
{
    public DateTime Week { get; set; }
    public bool Meeting { get; set; }
    public int NumClasses { get; set; }
    public string Host { get; set; }
    public string Cohost { get; set; }
    public string Chairman { get; set; }
    public string AuxCounsellor1 { get; set; }
    public string AuxCounsellor2 { get; set; }
    public string PrayerOpen { get; set; }
    public string PrayerClose { get; set; }
    public string CBSConductor { get; set; }
    public string CBSReader { get; set; }
    public List<MSAHistoryItemTalk> TalkItems { get; set; }
    public List<string> Teaching { get; set; }
    public List<string> StudentItemStudyNumbers { get; set; }
    public List<string> StudentItemDescriptions { get; set; }
    public int NumStudentItems { get; set; }
    public List<MSAHistoryItemStudent>[] StudentItems { get; set; }
    public MSAHistoryWeek()
    {
        TalkItems = Enumerable.Range(1, 6).Select(x => new MSAHistoryItemTalk()).ToList();
        Teaching = Enumerable.Range(1, 3).Select(x => string.Empty).ToList();
        StudentItemStudyNumbers = Enumerable.Range(1, 5).Select(x => string.Empty).ToList();
        StudentItemDescriptions = Enumerable.Range(1, 5).Select(x => string.Empty).ToList();
        StudentItems = new List<MSAHistoryItemStudent>[]
        {
            Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
            Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
            Enumerable.Range(1, 5).Select(x => new MSAHistoryItemStudent()).ToList(),
        };
    }

    public override string ToString()
    {
        return Week.ToShortDateString();
    }
}

第 2 步

我将 MSAHistoryWeek object 的一个实例添加到与 CsvReader 一起使用的 class 的修改版本中:

public class CLMExplorerHistory
{
    [Format("dd/MM/yyyy")]
    [Name("Date")]
    public DateTime Date { get => HistoryWeek.Week; set => HistoryWeek.Week = value; }

    [BooleanFalseValues(new string[] { "N", "n" })]
    [BooleanTrueValues(new string[] { "Y", "y" })]
    [Name("Meeting?")]
    public bool Meeting { get => HistoryWeek.Meeting; set => HistoryWeek.Meeting = value; }

    [Name("# Classes")]
    public int Classes { get => HistoryWeek.NumClasses; set => HistoryWeek.NumClasses = value; }

    [Name("Chairman")]
    public string Chairman { get => HistoryWeek.Chairman; set => HistoryWeek.Chairman = value; }

    [Name("AuxCounselor B")]
    public string AuxCounsellor1 { get => HistoryWeek.AuxCounsellor1; set => HistoryWeek.AuxCounsellor1 = value; }

    [Name("AuxCounselor C")]
    public string AuxCounsellor2 { get => HistoryWeek.AuxCounsellor2; set => HistoryWeek.AuxCounsellor2 = value; }

    [Name("PrayerOpen")]
    public string PrayerOpen { get => HistoryWeek.PrayerOpen; set => HistoryWeek.PrayerOpen = value; }

    [Name("PrayerClose")]
    public string PrayerClose { get => HistoryWeek.PrayerClose; set => HistoryWeek.PrayerClose = value; }

    [Name("CBS")]
    public string CBSConductor { get => HistoryWeek.CBSConductor; set => HistoryWeek.CBSConductor = value; }

    [Name("CBS_Read")]
    public string CBSReader { get => HistoryWeek.CBSReader; set => HistoryWeek.CBSReader = value; }

    [Name("TreasuresTalk")]
    public string TreasuresTalkName { get => HistoryWeek.TalkItems[0].Name; set => HistoryWeek.TalkItems[0].Name = value; }

    [Name("TreasuresTalk_Theme")]
    public string TreasuresTalkTheme { get => HistoryWeek.TalkItems[0].Theme; set => HistoryWeek.TalkItems[0].Theme = value; }

    [Name("TreasuresDigging")]
    public string SpiritualGemsName { get => HistoryWeek.TalkItems[1].Name; set => HistoryWeek.TalkItems[1].Name = value; }

    [Name("LivingPart1")]
    public string LivingPart1Name { get => HistoryWeek.TalkItems[3].Name; set => HistoryWeek.TalkItems[3].Name = value; }

    [Name("LivingPart1_Theme")]
    public string LivingPart1Theme { get => HistoryWeek.TalkItems[3].Theme; set => HistoryWeek.TalkItems[3].Theme = value; }

    [Name("LivingPart2")]
    public string LivingPart2Name { get => HistoryWeek.TalkItems[4].Name; set => HistoryWeek.TalkItems[4].Name = value; }

    [Name("LivingPart2_Theme")]
    public string LivingPart2Theme { get => HistoryWeek.TalkItems[4].Theme; set => HistoryWeek.TalkItems[4].Theme = value; }

    [Name("BibleReading_A")]
    public string BibleReadingClass1Name { get => HistoryWeek.StudentItems[0][0].Name; set => HistoryWeek.StudentItems[0][0].Name = value; }

    [Name("BibleReading_B")]
    public string BibleReadingClass2Name { get => HistoryWeek.StudentItems[1][0].Name; set => HistoryWeek.StudentItems[1][0].Name = value; }

    [Name("BibleReading_C")]
    public string BibleReadingClass3Name { get => HistoryWeek.StudentItems[2][0].Name; set => HistoryWeek.StudentItems[2][0].Name = value; }

    [Name("BibleReading_Study_A")]
    public string BibleReadingStudy { get => HistoryWeek.StudentItemStudyNumbers[0]; set => HistoryWeek.StudentItemStudyNumbers[0] = value; }

    [Name("Apply1_Description")]
    public string StudentItem1Description { get => HistoryWeek.StudentItemDescriptions[1]; set => HistoryWeek.StudentItemDescriptions[1] = value; }

    [Name("Apply2_Description")]
    public string StudentItem2Description { get => HistoryWeek.StudentItemDescriptions[2]; set => HistoryWeek.StudentItemDescriptions[2] = value; }

    [Name("Apply3_Description")]
    public string StudentItem3Description { get => HistoryWeek.StudentItemDescriptions[3]; set => HistoryWeek.StudentItemDescriptions[3] = value; }

    [Name("Apply4_Description")]
    public string StudentItem4Description { get => HistoryWeek.StudentItemDescriptions[4]; set => HistoryWeek.StudentItemDescriptions[4] = value; }

    [Name("Apply1_A")]
    public string StudentItem1Class1StudentName { get => HistoryWeek.StudentItems[0][1].Name; set => HistoryWeek.StudentItems[0][1].Name = value; }

    [Name("Apply1_B")]
    public string StudentItem1Class2StudentName { get => HistoryWeek.StudentItems[1][1].Name; set => HistoryWeek.StudentItems[1][1].Name = value; }

    [Name("Apply1_C")]
    public string StudentItem1Class3StudentName { get => HistoryWeek.StudentItems[2][1].Name; set => HistoryWeek.StudentItems[2][1].Name = value; }

    [Name("Apply1_Asst_A")]
    public string StudentItem1Class1AssistantName { get => HistoryWeek.StudentItems[0][1].Assistant; set => HistoryWeek.StudentItems[0][1].Assistant = value; }

    [Name("Apply1_Asst_B")]
    public string StudentItem1Class2AssistantName { get => HistoryWeek.StudentItems[1][1].Assistant; set => HistoryWeek.StudentItems[1][1].Assistant = value; }

    [Name("Apply1_Asst_C")]
    public string StudentItem1Class3AssistantName { get => HistoryWeek.StudentItems[2][1].Assistant; set => HistoryWeek.StudentItems[2][1].Assistant = value; }

    [Name("Apply2_A")]

    public string StudentItem2Class1StudentName { get => HistoryWeek.StudentItems[0][2].Name; set => HistoryWeek.StudentItems[0][2].Name = value; }

    [Name("Apply2_B")]
    public string StudentItem2Class2StudentName { get => HistoryWeek.StudentItems[1][2].Name; set => HistoryWeek.StudentItems[1][2].Name = value; }

    [Name("Apply2_C")]
    public string StudentItem2Class3StudentName { get => HistoryWeek.StudentItems[2][2].Name; set => HistoryWeek.StudentItems[2][2].Name = value; }

    [Name("Apply2_Asst_A")]
    public string StudentItem2Class1AssistantName { get => HistoryWeek.StudentItems[0][2].Assistant; set => HistoryWeek.StudentItems[0][2].Assistant = value; }

    [Name("Apply2_Asst_B")]
    public string StudentItem2Class2AssistantName { get => HistoryWeek.StudentItems[1][2].Assistant; set => HistoryWeek.StudentItems[1][2].Assistant = value; }

    [Name("Apply2_Asst_C")]
    public string StudentItem2Class3AssistantName { get => HistoryWeek.StudentItems[2][2].Assistant; set => HistoryWeek.StudentItems[2][2].Assistant = value; }

    [Name("Apply3_A")]
    public string StudentItem3Class1StudentName { get => HistoryWeek.StudentItems[0][3].Name; set => HistoryWeek.StudentItems[0][3].Name = value; }

    [Name("Apply3_B")]
    public string StudentItem3Class2StudentName { get => HistoryWeek.StudentItems[1][3].Name; set => HistoryWeek.StudentItems[1][3].Name = value; }

    [Name("Apply3_C")]
    public string StudentItem3Class3StudentName { get => HistoryWeek.StudentItems[2][3].Name; set => HistoryWeek.StudentItems[2][3].Name = value; }

    [Name("Apply3_Asst_A")]
    public string StudentItem3Class1AssistantName { get => HistoryWeek.StudentItems[0][3].Assistant; set => HistoryWeek.StudentItems[0][3].Assistant = value; }

    [Name("Apply3_Asst_B")]
    public string StudentItem3Class2AssistantName { get => HistoryWeek.StudentItems[1][3].Assistant; set => HistoryWeek.StudentItems[1][3].Assistant = value; }

    [Name("Apply3_Asst_C")]
    public string StudentItem3Class3AssistantName { get => HistoryWeek.StudentItems[2][3].Assistant; set => HistoryWeek.StudentItems[2][3].Assistant = value; }

    [Name("Apply4_A")]
    public string StudentItem4Class1StudentName { get => HistoryWeek.StudentItems[0][4].Name; set => HistoryWeek.StudentItems[0][4].Name = value; }

    [Name("Apply4_B")]
    public string StudentItem4Class2StudentName { get => HistoryWeek.StudentItems[1][4].Name; set => HistoryWeek.StudentItems[1][4].Name = value; }

    [Name("Apply4_C")]
    public string StudentItem4Class3StudentName { get => HistoryWeek.StudentItems[2][4].Name; set => HistoryWeek.StudentItems[2][4].Name = value; }

    [Name("Apply4_Asst_A")]
    public string StudentItem4Class1AssistantName { get => HistoryWeek.StudentItems[0][4].Assistant; set => HistoryWeek.StudentItems[0][4].Assistant = value; }

    [Name("Apply4_Asst_B")]
    public string StudentItem4Class2AssistantName { get => HistoryWeek.StudentItems[1][4].Assistant; set => HistoryWeek.StudentItems[1][4].Assistant = value; }

    [Name("Apply4_Asst_C")]
    public string StudentItem4Class3AssistantName { get => HistoryWeek.StudentItems[2][4].Assistant; set => HistoryWeek.StudentItems[2][4].Assistant = value; }

    [Name("Apply1_Study_A")]
    public string StudentItem1Study { get => HistoryWeek.StudentItemStudyNumbers[1]; set => HistoryWeek.StudentItemStudyNumbers[1] = value; }

    [Name("Apply2_Study_A")]
    public string StudentItem2Study { get => HistoryWeek.StudentItemStudyNumbers[2]; set => HistoryWeek.StudentItemStudyNumbers[2] = value; }

    [Name("Apply3_Study_A")]
    public string StudentItem3Study { get => HistoryWeek.StudentItemStudyNumbers[3]; set => HistoryWeek.StudentItemStudyNumbers[3] = value; }

    [Name("Apply4_Study_A")]
    public string StudentItem4Study { get => HistoryWeek.StudentItemStudyNumbers[4]; set => HistoryWeek.StudentItemStudyNumbers[4] = value; }

    [Ignore]
    public MSAHistoryWeek HistoryWeek;

    public CLMExplorerHistory()
    {
        HistoryWeek = new MSAHistoryWeek();
    }
}

如您所见,它遵循已接受答案中的原则,将 public CSV 属性映射到增强的 MSAHistoryWeek object.


结果

此重构使处理数据(即写入 XML)变得更加容易。