如何将EnumConverter与CsvHelper一起使用

时间:2015-07-28 03:32:13

标签: c# csv enums csvhelper converters

我正在使用CsvHelper将类序列化为csv文件 - 直到此处一切正常。

现在我正在尝试找到一种方法将类的枚举属性转换为csv中的int值,因此我可以稍后使用CSV进行批量插入。

我在CsvHelper中发现了EnumConverter类,但我无法弄清楚如何正确使用它,因为我的所有尝试都失败了。

这是我的映射类代码

 public sealed class MyMapping : CsvClassMap<TradingCalendarException>
    {
        public MyMapping()
        {
            EnumConverter enumConverter = new EnumConverter(typeof(CalendarExceptionEntityType));

            Map(m => m.ExceptionEntityType).Index(0).Name("EXCEPTION_ENTITY_TYPE").TypeConverter(enumConverter);
            Map(m => m.ExceptionEntityIdentifier).Index(1).Name("EXCEPTION_ENTITY_IDENTIFIER");
            Map(m => m.OptionType).Index(2).Name("OPTION_TYPE");
            Map(m => m.StartDatetime).Index(3).Name("EXCEPTION_START_DATETIME");
            Map(m => m.EndDatetime).Index(4).Name("EXCEPTION_END_DATETIME");
            Map(m => m.DataSourceType).Index(5).Name("DATA_SOURCE_TYPE");
            Map(m => m.Description).Index(6).Name("DESCRIPTION");
        }
    }

和写作部分

using (StreamWriter file = new StreamWriter(filePath, false, Encoding.UTF8))
        {
            CsvWriter writer = new CsvWriter(file);
            MyMapping mapping = new MyMapping();
            writer.Configuration.RegisterClassMap(mapping);

            writer.WriteRecords(calendarExceptionList);
        }

映射的其余部分(索引和命名)正在运行,只是EnumConverter没有做任何更改。

我没有在网上找到任何例子。

谢谢!

4 个答案:

答案 0 :(得分:4)

这是我提出的解决方案:

public class CalendarExceptionEnumConverter<T> : DefaultTypeConverter  where T : struct
    {
        public override string ConvertToString(TypeConverterOptions options, object value)
        {
            T result;
            if(Enum.TryParse<T>(value.ToString(),out result))
            {
                return (Convert.ToInt32(result)).ToString();
            }

            throw new InvalidCastException(String.Format("Invalid value to EnumConverter. Type: {0} Value: {1}",typeof(T),value));
        }
    }

并将其用作以下内容:

Map(m => m.ExceptionEntityType).TypeConverter<CalendarExceptionEnumConverter<CalendarExceptionEntityType>>();

答案 1 :(得分:4)

我使用了Yarimi的解决方案,但发现它无法从.csv读取枚举值(可以写好)

我的解决方案是让类从EnumTypeConverter扩展,而不是DefaultTypeConverter。

这是完整的代码

    public class OurEnumConverter<T> : CsvHelper.TypeConversion.EnumConverter where T : struct
    {

        public OurEnumConverter(): base(typeof(T))
        { }

        public override string ConvertToString(CsvHelper.TypeConversion.TypeConverterOptions options, object value)
        {
            T result;
            if (Enum.TryParse<T>(value.ToString(), out result))
            {
                return (Convert.ToInt32(result)).ToString();
            }
            return base.ConvertToString(options, value);
            //throw new InvalidCastException(String.Format("Invalid value to EnumConverter. Type: {0} Value: {1}", typeof (T), value));
        }
        public override object ConvertFromString(TypeConverterOptions options, string text)
        {
            int parsedValue;
            //System.Diagnostics.Debug.WriteLine($"{typeof(T).Name} = {text}");
            if (Int32.TryParse(text, out parsedValue))
            {
                return (T)(object)parsedValue;
            }
            return base.ConvertFromString(options, text);
            //throw new InvalidCastException(String.Format("Invalid value to EnumConverter. Type: {0} Value: {1}", typeof(T), text));
        }

    }

以及它是如何使用的

public class TickTradeClassMap : CsvHelper.Configuration.CsvClassMap<TickData.TickTrade>
    {
        public TickTradeClassMap()
        {
            Map(m => m.price);
            Map(m => m.size);
            Map(m => m.exchange).TypeConverter<OurEnumConverter<ATExchangeEnum>>();
            Map(m => m.condition1).TypeConverter<OurEnumConverter<ATTradeConditionEnum>>();
        }
    }

答案 2 :(得分:0)

在您的int课程中添加TradingCalendarException媒体资源,该课程会来回播放您的自定义枚举CalendarExceptionEntityType,例如:

public int ExceptionEntityTypeInt { 
    get { return (int)ExceptionEntityType; } 
    set { ExceptionEntityType = (CalendarExceptionEntityType)value; } 
}

使用Map(m => m.ExceptionEntityTypeInt).Index(0).Name("EXCEPTION_ENTITY_TYPE_INT")代替您的枚举转换器Map(m => m.ExceptionEntityType).Index(0).Name("EXCEPTION_ENTITY_TYPE").TypeConverter(new MyMapping())

答案 3 :(得分:0)

这是我对CSV Helper最新版本7.1.1所做的操作:

public class AggregateEnumConverter<T> : EnumConverter where T : struct
{
    public AggregateEnumConverter() : base(typeof(T)) { }

    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if(!Enum.TryParse(text, out AggregateType aggregateType))
        {
            // This is just to make the user life simpler...
            if(text == "24HAVG")
            {
                return AggregateType._24HAVG;
            }

            // If an invalid value is found in the CSV for the Aggregate column, throw an exception...
            throw new InvalidCastException($"Invalid value to EnumConverter. Type: {typeof(T)} Value: {text}");
        }

        return aggregateType;
    }
}

注意:上面的代码正在使用C#7新的内联输出变量。
更多信息在这里:How should I convert a string to an enum in C#?

这是您使用自定义EnumConverter的方式:

/// <summary>
/// Maps Tag class properties to the CSV columns' names
/// </summary>
public sealed class TagMap : ClassMap<Tag>
{
    public TagMap(ILogger<CsvImporter> logger)
    {
        Map(tag => tag.Aggregate).Name("aggregate").TypeConverter<AggregateEnumConverter<AggregateType>>();
    }
}