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

C# 为Serializable类新增属性后反序列化报找不到程序集如何解决

问题根因

该异常触发的本质是旧版本客户端的程序集中不存在你新增的NewType结构体定义,也没有新增了property3字段的SerializableClass版本定义。BinaryFormatter是强类型绑定的序列化机制,即使你设置了FormatterAssemblyStyle.Simple忽略程序集版本和公钥匹配,只要找不到对应的类型定义,就会抛出程序集/类型找不到的异常。

改用List类型能否解决问题?

完全不能。无论是数组还是List<NewType>,都依赖NewType这个类型的元数据才能完成反序列化,旧客户端不存在该类型的情况下,更换集合类型没有任何作用。

可行解决方案

方案1:无需修改旧客户端的适配方案

如果你无法对旧客户端进行发版更新,可在新版本的类定义中自定义序列化逻辑,仅当序列化目标为新版本客户端时才写入新增字段:

  1. 让SerializableClass实现ISerializable接口,自主控制序列化写入的字段
  2. 反序列化时主动判断是否存在新增字段,不存在则赋值为默认值
[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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:18:01