Применить пользовательский конвертер CsvHelper ко всем строковым свойствам набора классов
Я использую превосходную библиотеку Джоша Клоузка CsvHelper для чтения CSV-файлов и загрузки их в базу данных с использованием структуры сущностей. Это все работает хорошо, за исключением одной вещи; CsvReader хранит пустую строку в файле csv как пустую строку в базе данных, и я хотел бы, чтобы это значение было пустым. Итак, я создал собственный конвертер, который позаботится об этом:
public class NullStringConverter : StringConverter
{
public override object ConvertFromString(TypeConverterOptions options, string text)
{
if (string.IsNullOrEmpty(text))
return null;
else
return base.ConvertFromString(options, text);
}
}
Я могу применить это к строковому свойству, используя либо свободный синтаксис карты, либо через атрибут, и теперь он будет вставлять NULL вместо пустой строки.
Поскольку у меня довольно много классов, содержащих ряд строковых атрибутов, я бы хотел избежать создания операторов Map для каждого из них. Я создал общий класс Map, который перечисляет все свойства и применяет пользовательский конвертер ко всем строковым свойствам. Вот какой у меня диван
public class DefaultStringMap<TEntity> : CsvClassMap<TEntity> where TEntity : AbstractAmtSourceEntity
{
public DefaultStringMap()
{
typeof(TEntity).GetProperties()
.Where(p => p.PropertyType == typeof(string))
.ToList()
.ForEach(p => Map(m => p.Name).TypeConverter<NullStringConverter>());
}
}
Вот AbstractAmtSourceEntity
мой базовый класс для всех моих классов сущностей. Вот мой класс читателя, который фактически получает данные:
public static void Read<TEntity>(TextReader reader, AmtSourceModel context) where TEntity : AbstractAmtSourceEntity
{
using (var csvReader = new CsvReader(reader))
{
csvReader.Configuration.WillThrowOnMissingField = false;
csvReader.Configuration.Delimiter = "|";
csvReader.Configuration.SkipEmptyRecords = true;
csvReader.Configuration.RegisterClassMap<DefaultStringMap<Entity1>>();
csvReader.Configuration.RegisterClassMap<DefaultStringMap<Entity2>>();
etc...
csvReader.Configuration.IgnoreReadingExceptions = true;
csvReader.Configuration.ReadingExceptionCallback = (ex, row) =>
{
_log.Warn($"Exception caught reading row {row}", ex);
_log.Debug($"Exception detail: {ex.Data["CsvHelper"]}");
};
var records = csvReader.GetRecords<TEntity>();
context.Set<TEntity>().AddRange(records);
context.SaveChanges();
}
}
Это не работает, однако, отображение не применяется, поэтому, очевидно, я что-то упустил. Может кто-нибудь сказать мне, что здесь не хватает?
1 ответ
Вы можете установить конвертеры глобально.
TypeConverterFactory.AddConverter( typeof( string ), new NullStringConverter() );
// or
TypeConverterFactory.AddConverter<string>( new NullStringConverter() );