I receive different CSV without header (we agreed about the content but not the format) from different customers, and I'm trying to build a generic class that can parse it hard coupling it with CSVHelper (who knows if tomorrow it is not supported anymore). For example the first customer send a CSV as "Name;Lastname;Age;Birthplace", the second customer send it as "Birthplace;Lastname;Firstname;Age", and another customer sends "Firstname;Lastname". I create a custom attribute in which I put the index expected, and at runtime I would like to add the IndexAttribute from CsvHelper.
partial class CustomAttribute : Attribute
{
public int Index { get; set; }
}
public class PersonCustomer1 : IPerson
{
[CustomAttribute(Index = 0)]
public string Name { get; set; }
[CustomAttribute(Index = 1)]
public string Lastname { get; set; }
[CustomAttribute(Index = 3)]
public int Age { get; set; }
}
public class PersonCustomer2 : IPerson
{
[CustomAttribute(Index = 2)]
public string Name { get; set; }
[CustomAttribute(Index = 1)]
public string Lastname { get; set; }
[CustomAttribute(Index = 0)]
public int Age { get; set; }
[CustomAttribute(Index = 3)]
public int Gender { get; set; }
}
The generic converter is build as
public class ConverterCsv<T>
{
public IEnumerable<T> Convert(FileInfo fileInfo)
{
IEnumerable<T> records = new List<T>();
using (var reader = fileInfo.OpenText())
using (var csv = new CsvReader(reader))
{
csv.Configuration.HasHeaderRecord = false;
csv.Configuration.RegisterClassMap<CsvGenericMap<T>>();
records = csv.GetRecords<T>().ToList();
}
return records;
}
}
public sealed class CsvGenericMap<T> : ClassMap<T>
{
public CsvGenericMap()
{
foreach (var property in typeof(T).GetProperties())
{
var attribute = property?.GetCustomAttribute<CustomAttribute>();
//what now? How should I inject the CsvHelper.Configuration.Attributes.Index attribute?
}
}
}
I would expect that any csv, with its custom attribute set, will fill the class.
public sealed class CsvGenericMap<T> : ClassMap<T>
{
public CsvGenericMap()
{
foreach (var property in typeof(T).GetProperties())
{
var attribute = property?.GetCustomAttribute<CustomAttribute>();
Map(typeof(T), property).Index(attribute.Index);
}
}
}