I am using CsvHelper
to read a CSV
file so I can write "some" of its columns to somewhere else. I don't have the name of headers beforehand so I couldn't use ClassMapper
. However I can get a List of the names of columns at runtime because they are provided in a separate file so if I can read that file I can fill up a List<string>
with name of the headers of the CSV
that I am reading.
My question is now how can I use Key names of the ExpandoObject so I can get the value from them? Remember at runtime I do have a List<string>
that holds the keys/header names.
The two commented-out lines below are what I tried but failed.
List<string> list = new List<string>();
list.Add("LastName");
using(var streamReader = new StreamReader(@"C:\csvtesting\myfile.csv"))
{
using(var csvReader = new CsvReader(streamReader, CultureInfo.InvariantCulture))
{
var records = csvReader.GetRecords<dynamic>().ToList();
var one = records.First();
//one.Where(v => v.Key == list[0]).Select(x => x.Value).FirstOrDefault(); // cannot cast error
//var ddd = one.list[0]; // crash
var iWish = one.LastName; // but how to do this dynamically?
}
}
One option is to use the fact that underlying type of dynamic
in this case would be ExpandoObject
which implements IDictionary<string, object>
:
var one = records.First() as IDictionary<string, object>;
var iWish = one[list[0]]; // or TryGetValue, also can check the headers
Note that you can process the csv "dynamically" without using dynamic
(which, I would argue, in general case should be avoided) but using while
loop and GetField
API (see the Reading by Hand doc):
using (var csv = new CsvReader(streamReader, CultureInfo.InvariantCulture))
{
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
string? iWish = csv.GetField(list[0]);
string? iWishByIndex = csv.GetField(0); // if it is first column
break; // just for sake of the example
}
}