代码之家  ›  专栏  ›  技术社区  ›  John Kattenhorn

使用CSVHelper序列化和取消序列化字典<TKey,Value>?

  •  0
  • John Kattenhorn  · 技术社区  · 3 年前

    是否可以使用字典中的CSVHelpers读取和写入CSV文件?

    以下是我的编写代码片段:

    using var writer = new StreamWriter(_filePath);
    using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
    if (_classMap != null)
    {
        csv.Context.RegisterClassMap(_classMap);
    }
    csv.WriteHeader(typeof(Dictionary<TKey, TValue>));
    csv.NextRecord();
    
    foreach (var value in _store)
    {
         csv.WriteRecord(new KeyValuePair<TKey,TValue>(value.Key,value.Value));
         csv.NextRecord();
    }
    

    以下是我的阅读代码片段:

    using var reader = new StreamReader(_filePath);
    using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
    _ = csv.Read();
    _ = csv.ReadHeader();
    
    if (_classMap != null)
    {
        csv.Context.RegisterClassMap(_classMap);
    }
    
    while (csv.Read())
    {
        var key = csv.GetField<TKey>(0);
        var value = csv.GetRecord<TValue>();
    
        _store[key] = value;
    }
    

    的形状 Dictionary 属于类型 <int,Sequence> 其中Sequence对象看起来像:

    public class Sequence
    {
        public int SequenceId { get; set; }
        public int NextId { get; set; }
    }
    

    我尝试了几种不同的方法来做到这一点,但每次都会出现以下异常:

    System.MissingMethodException: Constructor 'CsvHelper.Configuration.DefaultClassMap`1[[System.Collections.Generic.KeyValuePair`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e0
    9],[FourDBS.SmartMeter.Common.Managers.Sequence, Four.DBS.Meadow.SmartMeter.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]()'
    
    0 回复  |  直到 3 年前
        1
  •  1
  •   David Specht    3 年前

    你很接近。你只需要写出字典id,然后写 Sequence 价值阅读也是如此。使用 GetField<int>("DictionaryId") 和 GetRecord<Sequence>() 。您可以使用 ClassMap<Sequence> 如果你想改变方式 序列 已写入。

    void Main()
    {
        var _filePath = @"C:\Temp\SerializeDictionary.csv";
        ClassMap<Sequence> _classMap = null;
    
        var data = new Dictionary<int, Sequence>(){
            { 1, new Sequence { SequenceId = 1, NextId = 2} },
            { 2, new Sequence { SequenceId = 2, NextId = 3} },
        };
    
        using (var writer = new StreamWriter(_filePath))
        using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
        {
            if (_classMap != null)
            {
                csv.Context.RegisterClassMap(_classMap);
            }
            csv.WriteField("DictionaryId");
            csv.WriteHeader<Sequence>();
            csv.NextRecord();
    
            foreach (var value in data)
            {
                csv.WriteRecord(value.Key);
                csv.WriteRecord(value.Value);
                csv.NextRecord();
            }
        }
    
    
        var _store = new Dictionary<int, Sequence>();
        using (var reader = new StreamReader(_filePath))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            _ = csv.Read();
            _ = csv.ReadHeader();
    
            if (_classMap != null)
            {
                csv.Context.RegisterClassMap(_classMap);
            }
    
            while (csv.Read())
            {
                var key = csv.GetField<int>("DictionaryId");
                var value = csv.GetRecord<Sequence>();
    
                _store[key] = value;
            }
        }
    }
    
    // You can define other methods, fields, classes and namespaces here
    public class Sequence
    {
        public int SequenceId { get; set; }
        public int NextId { get; set; }
    }
    
        2
  •  0
  •   Houtamelo    3 年前

    为什么不创建一个特定于序列化/反序列化过程的类型?

    public record DataRow(int Key, Sequence Value);
    
    using var writer = new StreamWriter(_filePath);
    using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
    if (_classMap != null)
    {
        csv.Context.RegisterClassMap(_classMap);
    }
    
    csv.WriteRecords(_store.Select(pair => new DataRow(pair.Key, pair.Value));
    

    以及用于阅读:

    using var reader = new StreamReader(_filePath);
    using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
    
    if (_classMap != null)
    {
        csv.Context.RegisterClassMap(_classMap);
    }
    
    foreach(DataRow row in csv.GetRecords<DataRow>())
    {
        if (row != null)
            _store[row.Key] = row.Value;
    }