Reputation: 184
I'm importing a csv of sales orders into CsvSalesOrder objects. The CsvSalesOrder has an Address property, and its properties are of a custom type called CustomString. How can I convert the strings into the CustomString types when importing them? My CustomString class:
public struct CustomString
{
public string Value { get; }
public CustomString(string val)
{
if (string.IsNullOrWhiteSpace(val))
{
Value = null;
}
else
{
Value = val.ToUpper();
}
}
public static implicit operator string(CustomString s) => s.Value;
public static explicit operator CustomString(string s) => new CustomString(s);
public override string ToString() => Value;
}
My mapping setup:
var config = new ChoCSVRecordConfiguration<T>()
.WithFirstLineHeader()
.Configure(c => c.ThrowAndStopOnMissingField = false)
.Configure(c => c.IgnoreEmptyLine = true)
.Configure(c => c.FileHeaderConfiguration.IgnoreColumnsWithEmptyHeader = true);
foreach (var header in headers)
{
if (mapping.TryGetValue(header, out var propName))
config.Map(propName, header);
}
My import code:
using var reader = new ChoCSVReader<T>(stream, config)
.WithMaxScanRows(2)
.QuoteAllFields()
.IgnoreFieldValueMode(ChoIgnoreFieldValueMode.Any);
return reader.AsTypedEnumerable<T>();
The Address fields are all null when I try to import. I tried adding a type converter as documented here, but it did not work.
ChoCSVRecordFieldConfiguration customStringConfig = new ChoCSVRecordFieldConfiguration("Address1");
customStringConfig.AddConverter(TypeDescriptor.GetConverter(typeof(CustomString)));
config.CSVRecordFieldConfigurations.Add(customStringConfig);
Upvotes: 0
Views: 134
Reputation: 184
I updated my code thanks to @Cinchoo's input.Here's the updated part:
using (var reader = new ChoCSVReader<T>(stream, config)
.WithMaxScanRows(2)
.QuoteAllFields()
.IgnoreFieldValueMode(ChoIgnoreFieldValueMode.Any)
)
{
return reader.AsTypedEnumerable<T>().ToList();
}
I had to add .ToList()
to get the list before the reader was disposed of. I also updated the using
syntax and the version of the ChoETL package.
Upvotes: 0
Reputation: 6332
You do not need custom value converters, as CustomString
already implemented implicit type conversion operators.
Here is the sample, on how do without converters
https://dotnetfiddle.net/uFrlCg
Here is a sample using converters
https://dotnetfiddle.net/ia5e50
Upvotes: 0
Reputation: 112712
Add your own TypeConverter
:
public class CustomStringTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string s) {
return new CustomString(s);
} else {
return base.ConvertFrom(context, culture, value);
}
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is CustomString customString) {
return customString.Value;
} else {
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
I don't know ChoETL , therefore I am not sure if this fixes the problem or if there are other configuration problems.
Upvotes: 0