【问题标题】:Apply CsvHelper custom converter to all string properties of a set of classes将 CsvHelper 自定义转换器应用于一组类的所有字符串属性
【发布时间】: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(); } } 然而,这不起作用,映射没有应用,所以很明显我错过了一些东西。谁能告诉我这里缺少什么?

【问题讨论】:

    标签: c# reflection csvhelper


    【解决方案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.TypeConverterCacheReference
    猜你喜欢
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多