将 CsvHelper 自定义转换器应用于一组类的所有字符串属性

Posted

技术标签:

【中文标题】将 CsvHelper 自定义转换器应用于一组类的所有字符串属性【英文标题】:Apply CsvHelper custom converter to all string properties of a set of classes 【发布时间】:2017-01-17 11:07:57 【问题描述】:

我正在使用 Josh Close 的优秀 CsvHelper 库来读取 csv 文件并使用实体框架将它们加载到数据库中。这一切都很好,除了一件事; CsvReader 将 csv 文件中的空字符串作为空字符串存储在数据库中,我希望这是一个 NULL 值。所以我所做的是创建一个自定义转换器来处理这个问题:

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() );

【讨论】:

超级棒,这就是我要找的。​​span> StringConverter 的全局覆盖在最新版本 (2.16.3) 中对我不起作用。如果我如问题中所述明确指定转换器,则可以正常工作。 请注意,从 3.0 版开始,TypeConverterFactory 现在称为 TypeConverterCache,可从您的 CsvReader 实例访问,例如reader.Configuration.TypeConverterCache。 Reference

以上是关于将 CsvHelper 自定义转换器应用于一组类的所有字符串属性的主要内容,如果未能解决你的问题,请参考以下文章

C# CSVhelper 无法使用自定义映射编写

工厂模式

使用 CsvHelper 将 csv 文件转换为 excel 时减少内存

CsvHelper 不验证是不是设置了转换

Java:动态加载同一类的多个版本

CsvHelper 动态列映射