Преобразовать вход CSV (1 поле) в класс назначения (2 поля) - PullRequest
0 голосов
/ 29 марта 2020

Я пишу свой ClassMap, который работает для моих первых полей c (включая те, у которых имя столбца не соответствует элементу класса). Но у меня есть 2 поля, которые нуждаются в конкретной работе

1) У меня есть цвет, хранящийся в виде строки. Мне нужен код, который преобразует входные данные в 2 значения и сохраняет каждое из них в указанном c члене.

2) У меня есть идентификатор, который соответствует идентификатору элемента CSV (это идентификатор отца или матери). Но мне нужно преобразовать его в идентификатор в моей базе данных (поэтому мне нужно написать некоторый код, который будет соответствовать CSV_ID и DB_ID).

Можно ли добавить эти пользовательские логи c с помощью CSVHelper? Спасибо за помощь. Винсент

1 Ответ

1 голос
/ 29 марта 2020

Как представляется, CSVHelper также поддерживает внедрение преобразователя того же типа во время отображения классов.

https://joshclose.github.io/CsvHelper/examples/configuration/class-maps/type-conversion

Объединяя это с поддержкой сопоставления поочередно имена,

https://joshclose.github.io/CsvHelper/examples/configuration/class-maps/mapping-by-alternate-names

Имея CSV-файл, подобный следующему:

Id,Name,Color
1,OGUZ OZGUL,#f0f0f0
2,VINCENT,#80A0C0
3,OZGUL OGUZ,#00A000

, можно достичь того, что необходимо, следующим образом:

using System;
using System.Globalization;
using System.IO;
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.TypeConversion;
using System.Linq;

namespace console
{
    public class Program
    {
        public class Foo
        {
            // Represents the database Id
            public int Id { get; set; }
            public string Name { get; set; }
            // Represents a three character color code, like #FFF
            public string Color3 { get; set; }
            // Represents a six character color code like #FFFFFF
            public string Color6 { get; set; }
        }

        // OK, we are not converting between types here, but who cares?
        // CSVHelper certainly doesn't.
        public class IdConverter : DefaultTypeConverter
        {
            public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
            {
                string csvId = text;
                int databaseId = Convert.ToInt32(text) + 10000;
                return databaseId;
            }

            public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
            {
                return ((int)value - 10000).ToString();
            }
        }

        // Again, we are changing the value as we wish, not the type.
        public class Color3Converter : DefaultTypeConverter
        {
            public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
            {
                // format: #ffffff
                return "#" + text[1] + text[3] + text[5];
            }

            public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
            {
                // format: #fff
                return "#" + ((string)value)[1] + "0" + ((string)value)[2] + "0" + ((string)value)[3] + "0";
            }
        }

        // By combining a type converter and alternative name
        // we achieve one CSV field value to be mapped to two properties
        // of our class Foo
        public sealed class FooMap : ClassMap<Foo>
        {
            public FooMap()
            {
                Map(m => m.Id).TypeConverter<IdConverter>();
                Map(m => m.Name);
                Map(m => m.Color3).TypeConverter<Color3Converter>().Name("Color");
                Map(m => m.Color6).Name("Color");
            }
        }

        static void Main(string[] args)
        {
            using (var reader = new StreamReader("data.csv"))
            {
                using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
                {
                    csv.Configuration.RegisterClassMap<FooMap>();
                    Foo[] records = csv.GetRecords<Foo>().ToArray();
                    foreach(Foo record in records)
                    {
                        Console.WriteLine
                        (
                            "Foo, Id: {0}, Name: {1}, Color3: {2}, Color6: {3}",
                             record.Id,
                             record.Name,
                             record.Color3,
                             record.Color6  
                        );
                }    
                }
            }
        }
    }
}

Вывод программы:

Foo, Id: 10001, Name: OGUZ OZGUL, Color3: #fff, Color6: #f0f0f0
Foo, Id: 10002, Name: VINCENT, Color3: #8AC, Color6: #80A0C0
Foo, Id: 10003, Name: OZGUL OGUZ, Color3: #0A0, Color6: #00A000
...