You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CSVHelper序列化/反序列化Dictionary<TKey,TValue>遇异常求助

能否用CSVHelper读写Dictionary类型的CSV文件?

问题背景

我需要用CSVHelper读写Dictionary<int, Sequence>类型的CSV文件,但尝试后抛出了MissingMethodException异常,相关代码和异常信息如下:

写入代码片段

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;
}

Sequence类定义

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

抛出的异常

System.MissingMethodException: Constructor 'CsvHelper.Configuration.DefaultClassMap1[[System.Collections.Generic.KeyValuePair2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e09],[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]]()'

解决方案

这个异常是因为CSVHelper尝试为KeyValuePair<TKey,TValue>创建默认类映射,但KeyValuePair是结构体,没有无参构造函数,导致映射创建失败。可以通过以下两种方式修复:

方式一:手动读写字段(简单直接)

修复写入逻辑

不需要依赖自动映射,手动定义表头并写入每个字段:

using var writer = new StreamWriter(_filePath);
using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);

// 写入自定义表头
csv.WriteField("Key");
csv.WriteField(nameof(Sequence.SequenceId));
csv.WriteField(nameof(Sequence.NextId));
csv.NextRecord();

// 遍历Dictionary写入每一行
foreach (var kvp in _store)
{
    csv.WriteField(kvp.Key);
    csv.WriteField(kvp.Value.SequenceId);
    csv.WriteField(kvp.Value.NextId);
    csv.NextRecord();
}

修复读取逻辑

对应写入格式,手动读取字段并构造对象:

using var reader = new StreamReader(_filePath);
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
csv.Read();
csv.ReadHeader();

while (csv.Read())
{
    var key = csv.GetField<int>("Key");
    var sequence = new Sequence
    {
        SequenceId = csv.GetField<int>(nameof(Sequence.SequenceId)),
        NextId = csv.GetField<int>(nameof(Sequence.NextId))
    };
    _store[key] = sequence;
}

方式二:自定义类映射(可复用)

为KeyValuePair<int, Sequence>创建自定义映射,明确指定每个字段的对应关系:

public class KeyValueSequenceMap : ClassMap<KeyValuePair<int, Sequence>>
{
    public KeyValueSequenceMap()
    {
        Map(m => m.Key).Name("Key");
        Map(m => m.Value.SequenceId).Name(nameof(Sequence.SequenceId));
        Map(m => m.Value.NextId).Name(nameof(Sequence.NextId));
    }
}

修复写入逻辑

注册自定义映射后直接写入键值对:

using var writer = new StreamWriter(_filePath);
using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<KeyValueSequenceMap>();

csv.WriteHeader<KeyValuePair<int, Sequence>>();
csv.NextRecord();

foreach (var kvp in _store)
{
    csv.WriteRecord(kvp);
    csv.NextRecord();
}

修复读取逻辑

注册相同的映射后读取成键值对:

using var reader = new StreamReader(_filePath);
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<KeyValueSequenceMap>();

csv.Read();
csv.ReadHeader();

while (csv.Read())
{
    var kvp = csv.GetRecord<KeyValuePair<int, Sequence>>();
    _store[kvp.Key] = kvp.Value;
}

核心原因

CSVHelper的默认类映射要求目标类型具备无参构造函数,但KeyValuePair<TKey,TValue>是结构体,仅提供带参构造函数,无法自动生成默认映射,因此抛出MissingMethodException。通过手动读写或自定义映射即可解决该问题。

内容的提问来源于stack exchange,提问作者John Kattenhorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:50:31