为何BinaryFormatter可序列化Action<>而Json.NET却无法实现?
Action<>序列化的结果差异这么大? 这问题问得好!核心原因其实是不同序列化工具对Action<>这类委托的处理逻辑完全不在一个频道上——毕竟委托本身就不是常规的“可序列化数据对象”,咱们拆开说:
1. 直接序列化Action<>失败的根本原因
Action<>本质是.NET里的委托类型,它存的不是数据,而是**方法的内存地址、目标对象引用(如果是实例方法)**这类运行时专属的信息。大多数通用序列化器(比如默认的DataContractSerializer、原生Json.NET)的设计目标是序列化“纯数据对象”——也就是有明确字段/属性、能映射成键值对或XML结构的东西。面对委托这种“非数据型”的类型,它们直接就懵了,自然会抛出“无法序列化”的异常。
2. BinaryFormatter + Base64能成功的原因
BinaryFormatter是个特殊的存在,它是.NET专门用来序列化对象完整运行时状态的工具,会钻到对象的底层结构里,连委托的方法指针、目标对象的序列化状态(只要目标对象支持序列化)都能抓下来。你转成Base64只是把二进制数据变成了文本格式方便传输/存储,核心还是BinaryFormatter的能力——它根本不关心是不是“数据对象”,只要是.NET对象的运行时状态,它就想办法给你存下来。
⚠️ 不过得提一句:BinaryFormatter现在已经被.NET官方标记为过时了,因为它有严重的安全漏洞,生产环境千万别用!
3. Json.NET的IFormatter模块失败的原因
你试的那个Json.NET格式化模块,本质还是基于Json.NET的核心逻辑。Json.NET的灵魂是把对象转成JSON——这种文本格式天生就是用来存“数据”的,键值对结构根本没法自然映射委托的方法引用。哪怕这个模块做了扩展,估计也没专门处理委托这种特殊类型的逻辑——毕竟JSON从设计之初就不是用来存储运行时方法指针这类东西的。
总结一下:
- 普通序列化器:只认“数据对象”,委托不是数据,所以失败
- BinaryFormatter:认“.NET对象的完整运行时状态”,委托的状态能被它捕捉,所以成功
- Json.NET系列:本质是JSON数据序列化,不兼容委托的非数据特性,所以失败
内容的提问来源于stack exchange,提问作者pm100

