john
john

Reputation: 1567

CsvHelper Field with name does not exist

I have this class and class map:

public class Subjects
{
    private readonly IEncryption _encryption;
    
    public Subjects(IEncryption encryption)
    {
        _encryption = encryption;
    }

    public Guid SubjectId { get; set; }
    public string Code { get; set; }
    public Guid OrganizationId { get; set; }
    public string PreferredName { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public string Gender { get; set; }
    public string LastNameInitial { get; set; }
    public string CodeDisplay { get; set; }
    public Guid? RaceId { get; set; }
    public Guid? MaritalStatusId { get; set; }
    public Guid? StatusId { get; set; }
    public string Rank { get; set; }
    public string Email { get; set; }
    public string MobilePhone { get; set; }
    public bool MobilePhoneDoNotLeaveMsg { get; set; }
    public bool MobilePhoneDoNotText { get; set; }
    public string WorkPhone { get; set; }
    public bool WorkPhoneDoNotLeaveMsg { get; set; }
}

public sealed class SubjectsMap : ClassMap<Subjects>
{
    public SubjectsMap()
    {
        AutoMap(CultureInfo.InvariantCulture);
        Map(m => m.Code).Name("Code");
        Map(m => m.OrganizationId).Name("OrganizationId");
        Map(m => m.PreferredName).Name("PreferredName");
        Map(m => m.FirstName).Name("FirstName");
        Map(m => m.MiddleName).Name("MiddleName");
        Map(m => m.LastName).Name("LastName");
        Map(m => m.DateOfBirth).Name("DateOfBirth");
        Map(m => m.Gender).Name("Gender");
        Map(m => m.LastNameInitial).Name("LastNameInitial");
        Map(m => m.CodeDisplay).Name("CodeDisplay");
        Map(m => m.RaceId).Name("RaceId");
        Map(m => m.MaritalStatusId).Name("MaritalStatusId");
        Map(m => m.StatusId).Name("StatusId");
        Map(m => m.Rank).Name("Rank");
        Map(m => m.Email).Name("Email");
        Map(m => m.MobilePhone).Name("MobilePhone");
        Map(m => m.MobilePhoneDoNotLeaveMsg).Name("MobilePhoneDoNotLeaveMsg");
        Map(m => m.MobilePhoneDoNotText).Name("MobilePhoneDoNotText");
        Map(m => m.WorkPhone).Name("WorkPhone");
        Map(m => m.WorkPhoneDoNotLeaveMsg).Name("WorkPhoneDoNotLeaveMsg");
    }
}

I have a constructor that injects an encryption method I need to use for some getters that will encrypt the string on a get. When I try to read the CSV into the class file:

public List<Subjects> ParseSubjectCSV(string inputFilePath)
    {
        using (var reader = new StreamReader(inputFilePath))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            csv.Configuration.RegisterClassMap<SubjectsMap>();
            csv.Configuration.HeaderValidated = null;
            var records = csv.GetRecords<Subjects>().ToList();
            return records;
        }
    }

I get this error:

Field with name 'encryption' does not exist. You can ignore missing fields by setting MissingFieldFound to null.

So I modified my code to add the MissingFieldFound to null and it kicks up the error:

The conversion cannot be performed Text:'' MemberType: TypeConverter "CsvHelper.TypeConvertion.DefaultTypeConverter".

If I remove the constructor and dependency injection then with works just fine. Can you use CSV to map to a class that has a constructor?

Upvotes: 1

Views: 1228

Answers (1)

Josh Close
Josh Close

Reputation: 23413

There is an ObjectResolver that creates objects that you can use.

void Main()
{
    var s = new StringBuilder();
    s.AppendLine("Id,Name");
    s.AppendLine("1,one");
    s.AppendLine("2,two");
    using (var reader = new StringReader(s.ToString()))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var bar = "bar";
        ObjectResolver.Current = new ObjectResolver(type => type == typeof(Foo), (type, constructorArgs) =>
        {
            return new Foo(bar);
        }, true);
        csv.Configuration.RegisterClassMap<FooMap>();
        csv.GetRecords<Foo>().ToList().Dump();
    }
}

public class Foo
{
    private readonly string bar;
    
    public int Id { get; set; }
    public string Name { get; set; }
    
    public Foo(string bar)
    {       
        this.bar = bar;
    }
}

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
    }
}

Upvotes: 1

Related Questions