C# 为Serializable类新增属性后反序列化报找不到程序集如何解决
问题根因
该异常触发的本质是旧版本客户端的程序集中不存在你新增的NewType结构体定义,也没有新增了property3字段的SerializableClass版本定义。BinaryFormatter是强类型绑定的序列化机制,即使你设置了FormatterAssemblyStyle.Simple忽略程序集版本和公钥匹配,只要找不到对应的类型定义,就会抛出程序集/类型找不到的异常。
改用List类型能否解决问题?
完全不能。无论是数组还是List<NewType>,都依赖NewType这个类型的元数据才能完成反序列化,旧客户端不存在该类型的情况下,更换集合类型没有任何作用。
可行解决方案
方案1:无需修改旧客户端的适配方案
如果你无法对旧客户端进行发版更新,可在新版本的类定义中自定义序列化逻辑,仅当序列化目标为新版本客户端时才写入新增字段:
- 让
SerializableClass实现ISerializable接口,自主控制序列化写入的字段 - 反序列化时主动判断是否存在新增字段,不存在则赋值为默认值
[Serializable] public class SerializableClass : ISerializable { public ExistingClass1[] property1; public ExistingClass2[] property2; public NewType[] property3; // 序列化逻辑 public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("property1", property1); info.AddValue("property2", property2); // 可根据上下文判断对端版本,仅高于指定版本才写入新增字段 if (context.Context is int targetVersion && targetVersion >= 2) { info.AddValue("property3", property3); } } // 反序列化构造函数 protected SerializableClass(SerializationInfo info, StreamingContext context) { property1 = (ExistingClass1[])info.GetValue("property1", typeof(ExistingClass1[])); property2 = (ExistingClass2[])info.GetValue("property2", typeof(ExistingClass2[])); // 存在新增字段则读取,否则赋值为空数组 property3 = info.FieldExists("property3") ? (NewType[])info.GetValue("property3", typeof(NewType[])) : Array.Empty<NewType>(); } }
方案2:可更新旧客户端的兼容方案
如果旧客户端可以发版更新,可给BinaryFormatter配置自定义序列化绑定器,忽略不存在的类型和字段:
public class CustomSerializationBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { try { var assembly = Assembly.Load(assemblyName); return assembly.GetType(typeName, throwOnError: false); } catch { // 找不到的类型直接返回null,反序列化时会自动赋值为对应类型的默认值 return null; } } } // 反序列化时指定自定义绑定器 BinaryFormatter formatter = new BinaryFormatter(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple; formatter.Binder = new CustomSerializationBinder(); using (MemoryStream r = new MemoryStream(bits)) { return formatter.Deserialize(r); }
长期优化建议
BinaryFormatter已被微软官方标记为不安全的API,且版本兼容性极差,长期来看建议迁移到兼容性更好、更安全的序列化方案,比如System.Text.Json、Protobuf等,这类序列化框架天然支持字段缺失的兼容处理,新增字段不会导致旧版本反序列化失败。
内容的提问来源于stack exchange,提问作者epsilon
相关产品推荐
相关产品推荐

