gpt4 book ai didi

c# - 使用 CSVHelper 如何使用子项列表反序列化 CSV

转载 作者:行者123 更新时间:2023-11-30 14:45:02 26 4
gpt4 key购买 nike

问题:

给包含 Bar 列表的对象 FooBarFooBarBar 定义如下:

class FooBar{
int FooID {get;set;}
string FooProperty1 {get;set;}
List<Bar> Bars {get;set;};
}

class Bar{
int BarID {get;set;}
string BarProperty1 {get;set;}
string BarProperty2 {get;set;}
string BarProperty3 {get;set;}
}

我得到以下 CSV 作为输入:

1,FooProperty1,BarID_1,BarProperty1_1,BarProperty2_1,BarProperty3_1,BarID_2,BarProperty1_2,BarProperty2_2,BarProperty3_2

其中字段 BarID、BarProperty1、BarProperty2、BarProperty3 以其在集合中的索引为后缀。

如何将此输入反序列化到我的对象中?

enter image description here


输入示例:

1 个 FooBar 实例和 2 个子 Bar:1,FooProperty1,BarID_1,BarProperty1_1,BarProperty2_1,BarProperty3_1,BarID_2,BarProperty1_2,BarProperty2_2,BarProperty3_2

1 个 FooBar 实例但没有 Bar:
1,FooProperty1


尝试:

我尝试使用 Convert 将这些属性映射到 Bar 的新实例,例如:

public class FooBarMap : ClassMap<FooBar> 
{
public FooBarMap()
{
Map(m => m.FooID);
Map(m => m.Bars).ConvertUsing(row =>
{
var list = new List<Bar>
{
new Bar {
BarProperty1 = row.GetField("BarProperty1_1"),
BarProperty2 = row.GetField("BarProperty2_1"),
// .. Other Properties
},
new Bar {}, //.. Same on _2
};
return list;
});
}
}

当然无法控制输入。我会发送 Json/Xml 而不是 CSV。

最佳答案

使用自定义类型转换器是可能的,但比较棘手。

您需要使用 Index 属性来装饰该属性(即使未使用)

public class FooBar
{
[Index(2)]
public List<Bar> Bars { get; set; }
}

converter既用于读又用于写,所以需要重写两个方法:

  public class BarListConverter : DefaultTypeConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
var list = new List<Bar>();
if (text == null) return list;
do
{
var barIndex = list.Count + 1;
var bar = new Bar
{
BarID = row.GetField<int>($"BarID_{barIndex}"),
BarProperty1 = row.GetField<string>($"BarProperty1_{barIndex}"),
BarProperty2 = row.GetField<string>($"BarProperty2_{barIndex}"),
BarProperty3 = row.GetField<string>($"BarProperty3_{barIndex}")
};
list.Add(bar);
} while (row.Context.CurrentIndex > 0 && row.Context.CurrentIndex < row.Context.Record.Length - 1);
return list;
}

public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
{
var bars = value as List<Bar>;
if (bars == null) return null;
foreach (var bar in bars)
{
row.WriteField(bar.BarID);
row.WriteField(bar.BarProperty1);
row.WriteField(bar.BarProperty2);
row.WriteField(bar.BarProperty3);
}
return null;
}
}
}

阅读:

  public List<FooBar> Reading()
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader))
{
writer.WriteLine(
"FooID,FooProperty1,BarID_1,BarProperty1_1,BarProperty2_1,BarProperty3_1,BarID_2,BarProperty1_2,BarProperty2_2,BarProperty3_2");
writer.WriteLine("1,Foo1,1,2,3,4,5,6,7,8");
writer.Flush();
stream.Position = 0;

csv.Configuration.HeaderValidated = null;
csv.Configuration.MissingFieldFound = null;
csv.Configuration.TypeConverterCache.AddConverter<List<Bar>>(new BarListConverter());

return csv.GetRecords<FooBar>().ToList();
}
}

写作:

  public string Writing(List<FooBar> data)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvWriter(writer))
{
csv.Configuration.HasHeaderRecord = false;
csv.Configuration.TypeConverterCache.AddConverter<List<Bar>>(new BarListConverter());
csv.WriteRecords(data);
writer.Flush();
stream.Position = 0;

return reader.ReadToEnd();
}

关于c# - 使用 CSVHelper 如何使用子项列表反序列化 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55745715/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com