Reputation: 5977
I need to parse incoming CSV files that mostly map to a specific class. However, the clients are permitted to add extra "user defined" fields to the end of record if they wish. So the CSV might look something like:
Id,FirstName,LastName,MyExtraField1,MyExtraField2
1,John,Doe,foo,bar
2,Jane,Smith,foo2,bar2
My class has named properties for Id, FirstName and LastName, but not for MyExtraField1 and MyExtraField2.
If I created a new property on the class called "ExtraFields" that was a Dict is it possible to take any field in the CSV that is not matched to the class and stuff it in the ExtraFields dictionary? The key would be the name of the field from the header and then the value for that record. Or is there some other way to capture these fields that don't map to any property in the class?
Upvotes: 2
Views: 1052
Reputation: 9074
I believe this gets what you are looking for.
static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader))
{
writer.WriteLine("Id,FirstName,LastName,MyExtraField1,MyExtraField2");
writer.WriteLine("1,John,Doe,foo,bar");
writer.WriteLine("2,Jane,Smith,foo2,bar2");
writer.Flush();
stream.Position = 0;
csv.Read();
csv.ReadHeader();
var headers = csv.Context.HeaderRecord.ToList();
csv.Configuration.RegisterClassMap(new TestClassMap(headers.Skip(3)));
var records = csv.GetRecords<TestClass>().ToList();
}
}
public class TestClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Dictionary<string, string> ExtraFields { get; set; }
}
public sealed class TestClassMap : ClassMap<TestClass>
{
public TestClassMap(IEnumerable<string> headers)
{
Map(m => m.Id);
Map(m => m.FirstName);
Map(m => m.LastName);
Map(m => m.ExtraFields).ConvertUsing(row => headers.ToDictionary(h => h, h => row.GetField(h)));
}
}
Upvotes: 1