使用CsvHelper,当我想要一个自定义解析器时(例如,我希望 MyBooleanConverter
,输入字符串为" f"将为false,&# 34; t"将" true")。但是每个班级我都要编写映射器:
public sealed class MyClassMap : CsvClassMap<MyClass>
{
public MyClassMap()
{
Map( m => m.Id ).Index( 0 ).TypeConverter<MyBooleanConverter>();
}
}
或者
[CsvHelper.TypeConversion.TypeConverter( typeof( MyBooleanConverter) )]
public Boolean MyObjectProperty { get; set; }
如何将MyBooleanConverter
设置为每个布尔字段和每个类的默认值?
答案 0 :(得分:4)
CsvHelper库公开了静态TypeConverterFactory
。您只需删除默认的布尔转换器并添加自定义转换器即可替换它。
TypeConverterFactory.RemoveConverter<bool>();
TypeConverterFactory.AddConverter<bool>(new MyBooleanConverter());
答案 1 :(得分:3)
只需将我的代码段添加到以下帖子中,以帮助理解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;
}
答案 2 :(得分:1)
也可以让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; }
}