Search code examples
c#nugetcsvhelper

CsvHelper Configuration.ShouldQuote - return true for only fields on the DTO which are strings


Hi have a DTO object with a number of properties with different types, string, int or bool etc.

I would like to apply double quotes around the string properties only.

In the Configuration.ShouldQuote the field parameter values have all been converted to string so there is no way of knowing whether the original type from the DTO was a string, int or bool.

Is there a way I can find the underlying property type from the DTO so that I can pass back true from Configuration.ShouldQuote only for fields that were originally of type string?

public class TestDTO
{
    public string Field1 { get; set; }
    public int Field2 { get; set; }
    public bool Field3 { get; set; }
}
    var rawData = new[]
    {
        new TestDTO { Field1 = "Field1", Field2 = 1, Field3 = true },
        new TestDTO { Field1 = "Field2", Field2 = 10, Field3 = false }
    };
    using (var writer = new StreamWriter("file.csv"))
    {
        using (var csv = new CsvWriter(writer))
        {
            csv.Configuration.ShouldQuote = (field, context) =>
            {
                return field is string; // doesn't work as all fields at this point are strings
            };

            csv.WriteRecords(rawData);
        }
    }

Solution

  • csv.Configuration.ShouldQuote = (field, context) =>
    {
        var index = context.Record.Count;
        var type = ((PropertyInfo)context.WriterConfiguration.Maps.Find<TestDTO>().MemberMaps[index].Data.Member).PropertyType;
        if (type == typeof(string))
        {
            return true;
        }
    
        return ConfigurationFunctions.ShouldQuote(field, context);
    };
    

    You can also use a custom converter.

    public class QuoteStringConverter : StringConverter
    {
        public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
        {
            var innerQuotes = ((string)value).Replace(row.Configuration.QuoteString, row.Configuration.DoubleQuoteString);
            var quotedValue = row.Configuration.Quote + innerQuotes + row.Configuration.Quote;
            return base.ConvertToString(quotedValue, row, memberMapData);
        }
    }
    

    Turn quotes off and add your converter to the TypeConverterCache

    var rawData = new[]
    {
        new TestDTO { Field1 = "Field1", Field2 = 1, Field3 = true },
        new TestDTO { Field1 = "Field2", Field2 = 10, Field3 = false }
    };
    
    using (var writer = new StreamWriter("file.csv"))
    using (var csv = new CsvWriter(writer))
    {
        csv.Configuration.ShouldQuote = (field, context) => false;
        csv.Configuration.TypeConverterCache.AddConverter<string>(new QuoteStringConverter());
    
        csv.WriteRecords(rawData);
    }