#c# #csv #mapping #csvhelper
#c# #csv #сопоставление #csvhelper
Вопрос:
Я пытаюсь сопоставить некоторые файлы, разделенные табуляцией переменного формата, с моим классом Foo:
public class Foo
{
public string A { get; set; }
public int? B { get; set; }
public double? C { get; set; }
}
Файл 1:
A B C
string 1 1.0
Файл 2:
Bee Sea
1 1.0
Когда формат заголовка постоянен, это легко сделать с помощью CSVHelper, используя CsvClassMap:
public sealed class FooMap : CsvClassMap<Foo>
{
public FooMap()
{
Map(x => x.A).Name("A");
Map(x => x.B).Name("B");
Map(x => x.C).Name("C");
}
}
Однако это становится сложным, когда формат заголовка является переменным.
- Файлы могут различаться по ширине и высоте.
- Порядок заголовков не фиксирован.
- Свойство определяется максимум один раз для каждого файла.
- Каждое свойство может относиться к различным именам заголовков.
- Имена заголовков являются эксклюзивными для одного свойства.
- Не все свойства обязательно определены в файле.
Каков был бы наилучший способ сопоставления с этим объектом?
Я полагаю, что я буду заполнять таблицу сопоставления заголовков со свойствами уникальным ключом в столбце заголовки, а затем искать соответствующее свойство каждого заголовка.
Текущее направление исследования:
public sealed class FooMap : CsvClassMap<Foo>
{
public FooMap()
{
}
public void SetHeaders(List<string> headers)
{
var dictionary = new Dictionary<string, List<string>>();
dictionary.Add("A", new List<string>() { "A", "Aay" });
dictionary.Add("B", new List<string>() { "B", "Bee" });
dictionary.Add("C", new List<string>() { "C", "Sea" });
...
}
}
Комментарии:
1. Имеют ли эти файлы какой-либо схожий формат? Например: все файлы содержат как минимум поля A и B.
2. @raidensan Скорее всего, но не обязательно. Файлы будут одним и тем же объектом, только с нулевыми значениями, где нет совпадающих столбцов.
Ответ №1:
Вы можете указать несколько имен для каждого свойства и сделать так, чтобы оно не выдавало исключение, если отсутствует поле.
Вот пример использования LINQPad:
void Main()
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader))
{
writer.WriteLine("A Bee C");
writer.WriteLine("string 1 1.0");
writer.Flush();
stream.Position = 0;
csv.Configuration.Delimiter = " ";
csv.Configuration.WillThrowOnMissingField = false;
csv.Configuration.RegisterClassMap<FooMap>();
csv.GetRecords<Foo>().ToList().Dump();
}
}
public class Foo
{
public string A { get; set; }
public int? B { get; set; }
public double? C { get; set; }
public Guid? D { get; set; }
}
public class FooMap : CsvClassMap<Foo>
{
public FooMap()
{
Map( m => m.A ).Name( "A", "Aay" );
Map( m => m.B ).Name( "B", "Bee" );
Map( m => m.C ).Name( "C", "Sea" );
Map( m => m.D ).Name( "D", "Dee" );
}
}
Результат:
A: string
B: 1
C: 1
D: null