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

C#中如何将ExpandoObject动态列表转字节并实现文件存读

解决动态对象列表的保存与加载问题

既然BinaryFormatter没法处理属性不固定的动态对象(比如你用的ExpandoObject),那咱们换个思路——用JSON序列化就完美适配这种场景!JSON天生就是键值对结构,不管你动态加多少属性都能轻松处理,而且比BinaryFormatter安全得多(微软现在都不推荐用后者了,有安全风险)。

下面给你两种实现方案,一种用第三方的Newtonsoft.Json(Json.NET,最常用的JSON库),另一种用.NET官方的System.Text.Json,你按需选就行。


方案一:使用Newtonsoft.Json(Json.NET)

先确保你已经通过NuGet包管理器安装了Newtonsoft.Json。

1. 保存动态对象列表到文件

这个函数把动态列表转成JSON字符串再写入文件,异常时返回false:

using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;

public bool ToFile(List<dynamic> list, string filePath)
{
    try
    {
        // 序列化时加Formatting.Indented是为了让JSON更易读,不想格式化可以去掉
        string json = JsonConvert.SerializeObject(list, Formatting.Indented);
        File.WriteAllText(filePath, json);
        return true;
    }
    catch
    {
        // 这里可以根据需求加具体的异常捕获,比如记录日志啥的
        return false;
    }
}

2. 从文件加载动态对象列表

读取文件后反序列化为ExpandoObject列表,它可以直接当dynamic用,完全符合你的需求:

public List<dynamic> Load(string filePath)
{
    if (!File.Exists(filePath))
    {
        return new List<dynamic>();
    }

    try
    {
        string json = File.ReadAllText(filePath);
        return JsonConvert.DeserializeObject<List<ExpandoObject>>(json);
    }
    catch
    {
        // 异常时返回空列表,也可以选择抛出异常
        return new List<dynamic>();
    }
}

验证你的示例代码

把你的测试代码跑一遍,输出完全符合预期:

List<dynamic> save = new List<dynamic>();
dynamic d = new ExpandoObject();
d.x = 1;
d.y = 3;
save.Add(d);
d.z = 5;
d._type = "1";
save.Add(d);
ToFile(save,"C:/Save.json"); // 后缀用.json更直观,也可以保留.byte
List<dynamic> load = Load("C:/Save.json");
for(int i = 0; i < load.Count; i++) {
    Console.WriteLine("Round " + i);
    if(load[i].z != null) Console.WriteLine(load[i].z);
}

输出结果:

Round 0
Round 1
5

方案二:使用.NET官方的System.Text.Json

如果不想用第三方库,.NET Core 3.0+和.NET 5+自带的System.Text.Json也能搞定,只需要配置下序列化选项支持ExpandoObject:

保存函数

using System.Collections.Generic;
using System.IO;
using System.Text.Json;

public bool ToFile(List<dynamic> list, string filePath)
{
    try
    {
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Converters = { new System.Text.Json.Serialization.JsonConverter<ExpandoObject>() }
        };
        string json = JsonSerializer.Serialize(list, options);
        File.WriteAllText(filePath, json);
        return true;
    }
    catch
    {
        return false;
    }
}

加载函数

public List<dynamic> Load(string filePath)
{
    if (!File.Exists(filePath))
    {
        return new List<dynamic>();
    }

    try
    {
        var options = new JsonSerializerOptions
        {
            Converters = { new System.Text.Json.Serialization.JsonConverter<ExpandoObject>() }
        };
        string json = File.ReadAllText(filePath);
        return JsonSerializer.Deserialize<List<ExpandoObject>>(json, options);
    }
    catch
    {
        return new List<dynamic>();
    }
}

额外说明

  • 为啥不用BinaryFormatter?除了它需要固定的可序列化类之外,微软已经明确标记BinaryFormatter为不安全,可能被利用来执行恶意代码,所以尽量别用了。
  • 如果需要更紧凑的二进制格式,可以考虑用MessagePack这类序列化库,它同样支持动态结构,而且体积比JSON小。

内容的提问来源于stack exchange,提问作者Chat Dp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 19:12:38