Reading a CSv file with CsvHelper you can specify the expected Header in the ClassMap
:
public sealed class readFooMapper : ClassMap<FooCSV>
{
public readFooMapper()
{
Map(m => m.Id).ConvertUsing(row => ((CsvReader)row).Parser.Context.RawRow);
Map(x => x.Foo).Name("Foo");
Map(x => x.Bar).Name("Bar");
Map(x => x.FooBar).Name("FooBar");
Map(x => x.MyOptional).Name("MyOptional").Optional();
}
}
Every property mapped is required and expected, optional is use to distiguish property that migh or might not be present.
Header are validate by Action<bool, string[], int, ReadingContext> HeaderValidated
, with the respective Arguments: isValid, headerNames, headerNameIndex, context.
When a header is not missing isValid is false. headerNames
and 'headerNameIndex' will respectivlly contains the expect names or index for the header.
I can use it to know with header is missing.
How can I access the list of expected header? Many properties of ReadingContext context
will hold the list of current header.
I can use the Validation loop to Add all the headerNames
and 'headerNameIndex' to a list.
var errorSb = new StringBuilder();
[...]
csvReader.Configuration.HeaderValidated =
(isValid, headerNames, headerNameIndex, context) =>
{
allHeaderNames.Add(headerNames);
if (!isRowValid)
{
isHeaderInvalid= true;
}
};
What I really want is the readFooMapper
mapping configuration.
To tell the user: "Look I expect This list of columns: ##, ##, ##. With those optional columns: X,Y,Z. \n Missing column = A,B,C."
And this without having to maintain one an other lists Headers and Optional.
I think this gets close to what you are looking for. It won't check if there is a column referenced in your ConvertUsing
method.
var map = new readFooMapper();
var required = map.MemberMaps
.Where(m => m.Data.Ignore == false
&& m.Data.ReadingConvertExpression == null
&& m.Data.IsOptional == false)
.Select(m => m.Data.Member.Name)
.ToList();
var optional = map.MemberMaps
.Where(m => m.Data.Ignore == false
&& m.Data.ReadingConvertExpression == null
&& m.Data.IsOptional == true)
.Select(m => m.Data.Member.Name)
.ToList();