CsvHelper 设置默认自定义 TypeConverter

yel*_*ver 5 c# csvhelper

使用 CsvHelper,当我想要一个自定义解析器时(例如,我想要一个MyBooleanConverter输入字符串为“f”的将是假的,“t”将是“真”)。但是对于每个课程,我都必须编写映射器:

public sealed class MyClassMap : CsvClassMap<MyClass>
{
    public MyClassMap()
    {
        Map( m => m.Id ).Index( 0 ).TypeConverter<MyBooleanConverter>();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者

[CsvHelper.TypeConversion.TypeConverter( typeof( MyBooleanConverter) )]
public Boolean MyObjectProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

如何将MyBooleanConverter每个布尔字段和每个类设置为默认值?

Mic*_*son 9

CsvHelper 库公开了一个静态的TypeConverterFactory. 您可以简单地删除默认的布尔转换器并添加您的自定义转换器来替换它。

TypeConverterFactory.RemoveConverter<bool>();
TypeConverterFactory.AddConverter<bool>(new MyBooleanConverter());
Run Code Online (Sandbox Code Playgroud)

  • 请注意,从 3.0 版本开始,`TypeConverterFactory` 现在被称为 `TypeConverterCache` 并且可以从你的 `CsvReader` 实例访问,例如 `reader.Configuration.TypeConverterCache`。[参考](https://github.com/JoshClose/CsvHelper/blob/04c764551c2d371e79edf162a543c3140316c48c/docs-src/src/pages/change-log.md#300) (7认同)
  • 从版本 20.0 开始,可以在您的读取器/写入器实例上访问类型转换器,例如“reader.Context.TypeConverterCache” (3认同)

小智 7

只需将我的代码片段添加到以下帖子中即可帮助理解 CsvHelper 中内置的类型转换器。我需要以以下格式“yyyyMMdd”处理日期,它似乎可以在没有 .net DateTime Parse 错误的情况下来回写入 CSV:“字符串未被识别为有效的 DateTime。”

using (TextWriter writer = new StreamWriter(csvLocaitonAndName))
        {
            var csvUpdate = new CsvWriter(writer);
            csvUpdate.Configuration.TypeConverterCache.AddConverter<DateTime?>(new DateConverter("yyyyMMdd"));
            csvUpdate.Configuration.HasHeaderRecord = false;
            csvUpdate.WriteRecords(list);
        }

public class DateConverter : ITypeConverter
    {
        private readonly string _dateFormat;

        public DateConverter(string dateFormat)
        {
            _dateFormat = dateFormat;
        }

        public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
        {
            if (!string.IsNullOrEmpty(text))
            {
                DateTime dt;
                DateTime.TryParseExact(text, _dateFormat,
                                       CultureInfo.InvariantCulture,
                                       DateTimeStyles.None,
                                       out dt);
                if (IsValidSqlDateTime(dt))
                {
                    return dt;
                }

            }

            return null;
        }
        public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
        {
            return ObjectToDateString(value, _dateFormat);
        }

        public string ObjectToDateString(object o, string dateFormat)
        {
            if (o == null) return string.Empty;

            DateTime dt;
            if (DateTime.TryParse(o.ToString(), out dt))
                return dt.ToString(dateFormat);
            else
                return string.Empty; 
        }
        public bool IsValidSqlDateTime(DateTime? dateTime)
        {
            if (dateTime == null) return true;

            DateTime minValue = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MinValue.ToString());
            DateTime maxValue = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MaxValue.ToString());

            if (minValue > dateTime.Value || maxValue < dateTime.Value)
                return false;

            return true;
        }
Run Code Online (Sandbox Code Playgroud)


Dav*_*ers 7

还可以让 CsvHelper 生成您的 ClassMap,此时您可以为您的成员自定义其处理。我发现这对于完成我的小爱好项目中的事情很有用。

var csv = new CsvReader(streamReader, false);
var classMap = csv.Configuration.AutoMap<Row>(); // ClassMap creation

// My price data has dollar signs so those need to be stripped out before parsing to a decimal
classMap.Map(row => row.Price).ConvertUsing(row => decimal.Parse(row.GetField("Price").Replace("$", "")));

// CsvHelper doesn't support URIs so that requires help as well
classMap.Map(row => row.Source).ConvertUsing(row => new Uri(row.GetField("Source")));

var prices = csv.GetRecords<Row>();



// my DTO
class Row
{
    public decimal Price { get; set; }
    public string ManufacturerSku { get; set; }
    public string Manufacturer { get; set; }
    public Uri Source { get; set; }
    public DateTimeOffset Extraction_Time { get; set; }
}
Run Code Online (Sandbox Code Playgroud)