Skip to content

Custom Types

jhgbrt edited this page Nov 12, 2020 · 5 revisions

You can define custom types for representing columns in your CSV file. NetCsv taps into the TypeDescriptor/TypeConverter ecosystem to realize this.

.NET has a built-in facility to facilitate type conversion, through the TypeConverter class. NetCsv taps into this system when using schema-based csv reading and writing.

As an example, suppose you have a custom value type that represents a currency, formatted as a string value with the currency, a space and the amount in decimal format:

public struct Amount
{
    public string Currency { get; set; }
    public decimal Value { get; set; }
    public static Amount Parse(string s, IFormatProvider provider)
    {
        var parts = s.Split(' ');
        var currency = parts[0];
        var decimalValue = decimal.Parse(parts[1], provider);
        return new Amount { Currency = currency, Value = decimalValue } ;
    }
    public string ToString(IFormatProvider provider)
    {
        return $"{Currency} {Value.ToString(provider)}";
    }

    public override string ToString() => ToString(CultureInfo.CurrentCulture);
}

Conversion of this type to and from a string can be implemented by providing a TypeConverter class similar to the following:

public class AmountConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        => sourceType == typeof(string);
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        => destinationType == typeof(Amount);
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string s) return Amount.Parse(s, culture);
        return base.ConvertFrom(context, culture, value);
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture,
                                     object value, Type destinationType)
    {
        if (value is Amount a && destinationType == typeof(string)) return a.ToString(culture);
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

As you can see, the ConvertFrom method can create an Amount from a string, while ConvertTo will handle conversion from Amount to string. By applying the TypeConverterAttribute to the Amount struct, NetCsv will use this converter to convert a string it reads in the CSV file to the Amount type:

[TypeConverter(typeof(AmountConverter))]
public struct Amount
{
    // etc...
}

Clone this wiki locally