Search code examples
c#csvhelper

CsvHelper: "Incorrect number of arguments for constructor" when using attributes to map properties


I'm reading data from a CSV using CsvHelper and despite using attributes above every field, it is throwing an error "Incorrect number of arguments for constructor." A sample is below:

public class MyClass {
    [Name("Id")]
    public int AwardId { get; set; }
    
    //[Ignore]
    public List<string> IgnoreList { get; set; }

    [Name("DateField")]
    public Tuple<DateTime, DateTime> TwoDates { get; set; }

    public MyClass() {
        IgnoreList = new();
    }
}

//In another class
public void LoadDataFromCSV(string Filepath)
{
    var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture)
        {
            MissingFieldFound = null,
            HeaderValidated = null,
        };
    using (var reader = new StreamReader(Filepath))
    using (var csv = new CsvReader(reader, config))
    {
       //***Error on this line***
       var records = csv.GetRecords<MyClass>().ToList();
    }
}

Here is a sample row of data:

Id, DateField
23659961,1/1/2001


Solution

  • CsvHelper will ignore lists, unless you specifically map them, so the [Ignore] above IgnoreList is not needed. You could use Convert in a ClassMap to create your Tuple.

    void Main()
    {
        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
        };
        
        using (var reader = new StringReader("Id,DateField1,DateField2\n1,1/5/2022,1/6/2022"))
        using (var csv = new CsvReader(reader, config))
        {
            csv.Context.RegisterClassMap<MyClassMap>();
            var records = csv.GetRecords<MyClass>().Dump();
        }
    }
    
    public class MyClass 
    {
        public int AwardId { get; set; }
    
        public List<string> IgnoreList { get; set; }
    
        public Tuple<DateTime, DateTime> TwoDates { get; set; }
    
        public MyClass()
        {
            IgnoreList = new();
        }
    }
    
    public class MyClassMap : ClassMap<MyClass>
    {
        public MyClassMap()
        {
            Map(x => x.AwardId).Name("Id");
            Map(x => x.TwoDates).Convert(args =>
            {
                var value = Tuple.Create(args.Row.GetField<DateTime>("DateField1"), args.Row.GetField<DateTime>("DateField2"));
                
                return value;
            });     
        }
    }