Как указано в заголовке, когда я заменяю преобразователь по умолчанию на CSVReader.Configuration.TypeConverterCache, он выдает исключение TypeConverterException, в котором говорится, что он использовал преобразователь по умолчанию вместо замены. Определение преобразователя для этого поля в ClassMap успешно использует заменяющий преобразователь.
Ниже приведена часть кода моего приложения, в которой воспроизводится проблема. В файле .csv, который я использую, есть несколько ненужных строк перед заголовком, поэтому они игнорируются, но я включил их в пример.
class Program {
static void Main(string[] args) {
List<Item> items = new List<Item>();
var s = new StringBuilder();
s.Append("WORD,,\r\n");
s.Append(",地区版本备注,是否测试道具\r\n");
s.Append("ID,Party,IsActive\r\n");
s.Append("1,1,0\r\n");
s.Append("2,1,1\r\n");
s.Append("3,1,,\r\n");
Console.WriteLine("Reading with replaced default converter.");
using (var reader = new StringReader(s.ToString())) {
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) {
csv.Configuration.Delimiter = ",";
csv.Configuration.RegisterClassMap<ItemMapWithConverter>();
csv.Configuration.TypeConverterCache.RemoveConverter<bool>();
csv.Configuration.TypeConverterCache.AddConverter<bool>(new BooleanConverter());
Console.WriteLine($"Configuration boolean converter type :: {csv.Configuration.TypeConverterCache.GetConverter<bool>()}");
csv.Configuration.ShouldSkipRecord = ShouldSkipRecord;
bool foundHeader = false;
while (csv.Read()) {
try {
if (csv.Context.Record[0].StartsWith("ID")) {
csv.ReadHeader();
foundHeader = true;
continue;
}
if (foundHeader)
items.Add(csv.GetRecord<Item>());
}
catch (TypeConverterException ex) {
Console.WriteLine($"Exception :: {ex.Message}");
Console.WriteLine($"RawRecord :: {ex.ReadingContext.RawRecord}");
continue;
}
}
}
}
Console.WriteLine();
Console.WriteLine("Reading with converter defined in ClassMap.");
using (var reader = new StringReader(s.ToString())) {
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) {
csv.Configuration.Delimiter = ",";
csv.Configuration.RegisterClassMap<ItemMapWithoutConverter>();
Console.WriteLine($"Configuration boolean converter type :: {csv.Configuration.TypeConverterCache.GetConverter<bool>()}");
csv.Configuration.ShouldSkipRecord = ShouldSkipRecord;
bool foundHeader = false;
while (csv.Read()) {
try {
if (csv.Context.Record[0].StartsWith("ID")) {
csv.ReadHeader();
foundHeader = true;
continue;
}
if (foundHeader)
items.Add(csv.GetRecord<Item>());
}
catch (TypeConverterException ex) {
Console.WriteLine($"Exception :: {ex.Message}");
Console.WriteLine($"RawRecord :: {ex.ReadingContext.RawRecord}");
continue;
}
}
}
}
Console.ReadKey();
}
private static bool ShouldSkipRecord(string[] fields) {
if (string.IsNullOrEmpty(fields[0]))
return true;
return false;
}
}
public class Item{
public int Id { get; set; }
public int Class { get; set; }
public bool IsActive { get; set; }
public Item() { }
}
public class ItemMapWithConverter : ClassMap<Item> {
public ItemMapWithConverter() {
Map(m => m.Id).Name("ID");
Map(m => m.Class).Name("Party");
Map(m => m.IsActive).Name("IsActive");
}
}
public class ItemMapWithoutConverter : ClassMap<Item> {
public ItemMapWithoutConverter() {
Map(m => m.Id).Name("ID");
Map(m => m.Class).Name("Party");
Map(m => m.IsActive).Name("IsActive").TypeConverter<BooleanConverter>();
}
}
public class BooleanConverter : DefaultTypeConverter {
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData) {
if (string.IsNullOrEmpty(text))
return false;
else
return Convert.ToBoolean(Convert.ToInt32(text));
}
public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData) {
if ((bool)value)
return "1";
else
return "0";
}
}
Итак, я что-то делаю неправильно при определении конвертеров по умолчанию или это ошибка?