Применить пользовательский конвертер 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() );
Другие вопросы по тегам