.NET 7中反序列化含MemoryStream的Serializable类报错排查
问题分析与解决方案
问题原因
.NET Framework 中 System.IO.MemoryStream 类型标记了 [Serializable] 特性,因此可以被 BinaryFormatter 正常序列化/反序列化。但从 .NET Core(包括 .NET 7)开始,MemoryStream 移除了该特性,导致用旧 .NET Framework 序列化的文件在 .NET 7 中反序列化时,触发 SerializationException,提示该类型未标记可序列化。
必要前提配置
由于 BinaryFormatter 在 .NET 5+ 中被标记为不安全且默认禁用,首先需要在项目文件(.csproj)中启用兼容性开关,否则无法使用该组件:
<PropertyGroup> <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> </PropertyGroup>
解决方案
方案1:使用序列化代理(无需修改原Quest类)
通过实现 ISerializationSurrogate 为 MemoryStream 自定义序列化/反序列化逻辑,让 BinaryFormatter 能识别并处理该类型。
代码实现
using System.Runtime.Serialization; using System.IO; public class MemoryStreamSurrogate : ISerializationSurrogate { // 处理序列化逻辑(若需要重新序列化新文件时生效) public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { var ms = (MemoryStream)obj; info.AddValue("Data", ms.ToArray()); } // 处理反序列化逻辑(核心:从旧文件的序列化数据重建MemoryStream) public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { byte[] data = (byte[])info.GetValue("Data", typeof(byte[])); return new MemoryStream(data); } } // 反序列化时的使用方式 var formatter = new BinaryFormatter(); var surrogateSelector = new SurrogateSelector(); // 为MemoryStream类型注册代理 surrogateSelector.AddSurrogate( typeof(MemoryStream), new StreamingContext(StreamingContextStates.All), new MemoryStreamSurrogate() ); formatter.SurrogateSelector = surrogateSelector; using (var fileStream = File.OpenRead("your-quest-file.dat")) { var quest = (Quest)formatter.Deserialize(fileStream); }
方案2:修改Quest类(替换MemoryStream为byte[])
若允许修改原 Quest 类,可以将 MemoryStream 属性替换为 byte[] 存储,通过序列化回调方法实现自动转换,既兼容旧文件,也能适配新框架。
代码实现
using System.Runtime.Serialization; using System.IO; [Serializable] public class Quest { // 存储序列化的流数据(对应旧文件中MemoryStream的内容) private byte[] _streamData; // 非序列化的MemoryStream实例,仅在运行时使用 [NonSerialized] private MemoryStream _memoryStream; // 对外暴露的MemoryStream属性 public MemoryStream QuestStream { get { if (_memoryStream == null && _streamData != null) { _memoryStream = new MemoryStream(_streamData); } return _memoryStream; } set { _memoryStream = value; _streamData = value?.ToArray(); } } // 反序列化完成后重建MemoryStream [OnDeserialized] private void OnDeserialized(StreamingContext context) { if (_streamData != null) { _memoryStream = new MemoryStream(_streamData); } } // 序列化前将MemoryStream转换为byte[] [OnSerialized] private void OnSerialized(StreamingContext context) { if (_memoryStream != null) { _streamData = _memoryStream.ToArray(); } } }
内容的提问来源于stack exchange,提问作者0xSingularity
相关产品推荐
相关产品推荐

