在 ClassMap ConvertUsing 方法中创建新记录
Create new record inside a ClassMap ConvertUsing method
案例是我正在解析一个文件,它看起来像这样。
Name
Account
Foo client
123
Bar client
456,789
在真实数据中我做了更多的事情,清理帐户等,但重点是帐户列中的 ,
。我现在得到一个有 2 条记录的 IEnumerable,我想得到一个有 3 条记录的 IEnumerable,方法是在“帐户”列中用逗号分隔记录。
像这样。
Name
Account
Foo client
123
Bar client
456
Bar client
789
是否可以通过 CSV Helper 实现?
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Read();
csvReader.ReadHeader();
var records = new List<Foo>();
while (csvReader.Read())
{
var name = csvReader.GetField("Name");
var account = csvReader.GetField("Account");
var splitAccounts = account.Split(",");
foreach(var item in splitAccounts)
{
records.Add(new Foo { Name = name, Account = int.Parse(item)});
}
}
records.Dump();
}
}
public class Foo
{
public string Name { get; set; }
public int Account { get; set; }
}
更新:
每一行都是一条记录,所以您真的不能用行外的 ClassMap
创建新记录。您可以做的是将您的 class 包装在另一个 class 中,其中包含您尝试创建的 List<MyClass>
个记录,然后将它们组合回单个 List<MyClass>
.如果 Account
可以在 MyClass
中输入 string
,你可以不用单独的 MyClassMap
就可以离开,只需让它 AutoMap()
你的 class.
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Configuration.RegisterClassMap<FooMap>();
csvReader.Configuration.RegisterClassMap<MyClassMap>();
var wrappedRecords = csvReader.GetRecords<Foo>();
var records = wrappedRecords.SelectMany(r => r.Clients).ToList();
records.Dump();
}
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(x => x.Clients).ConvertUsing(x =>
{
var records = new List<MyClass>();
var record = x.GetRecord<MyClass>();
var splitAccounts = x.GetField("Account").Split(",");
foreach (var item in splitAccounts)
{
records.Add(new MyClass { Name = record.Name, Account = int.Parse(item) });
}
return records;
});
}
}
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Map(x => x.Name);
}
}
public class Foo
{
public List<MyClass> Clients { get; set; }
}
public class MyClass
{
public string Name { get; set; }
public int Account { get; set; }
}
案例是我正在解析一个文件,它看起来像这样。
Name | Account |
---|---|
Foo client | 123 |
Bar client | 456,789 |
在真实数据中我做了更多的事情,清理帐户等,但重点是帐户列中的 ,
。我现在得到一个有 2 条记录的 IEnumerable,我想得到一个有 3 条记录的 IEnumerable,方法是在“帐户”列中用逗号分隔记录。
像这样。
Name | Account |
---|---|
Foo client | 123 |
Bar client | 456 |
Bar client | 789 |
是否可以通过 CSV Helper 实现?
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Read();
csvReader.ReadHeader();
var records = new List<Foo>();
while (csvReader.Read())
{
var name = csvReader.GetField("Name");
var account = csvReader.GetField("Account");
var splitAccounts = account.Split(",");
foreach(var item in splitAccounts)
{
records.Add(new Foo { Name = name, Account = int.Parse(item)});
}
}
records.Dump();
}
}
public class Foo
{
public string Name { get; set; }
public int Account { get; set; }
}
更新:
每一行都是一条记录,所以您真的不能用行外的 ClassMap
创建新记录。您可以做的是将您的 class 包装在另一个 class 中,其中包含您尝试创建的 List<MyClass>
个记录,然后将它们组合回单个 List<MyClass>
.如果 Account
可以在 MyClass
中输入 string
,你可以不用单独的 MyClassMap
就可以离开,只需让它 AutoMap()
你的 class.
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Configuration.RegisterClassMap<FooMap>();
csvReader.Configuration.RegisterClassMap<MyClassMap>();
var wrappedRecords = csvReader.GetRecords<Foo>();
var records = wrappedRecords.SelectMany(r => r.Clients).ToList();
records.Dump();
}
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(x => x.Clients).ConvertUsing(x =>
{
var records = new List<MyClass>();
var record = x.GetRecord<MyClass>();
var splitAccounts = x.GetField("Account").Split(",");
foreach (var item in splitAccounts)
{
records.Add(new MyClass { Name = record.Name, Account = int.Parse(item) });
}
return records;
});
}
}
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Map(x => x.Name);
}
}
public class Foo
{
public List<MyClass> Clients { get; set; }
}
public class MyClass
{
public string Name { get; set; }
public int Account { get; set; }
}