如何用BinaryFormatter反序列化未知类型.NET对象并转为null
处理BinaryFormatter反序列化未知类型时返回null的方案
我之前刚好解决过一模一样的问题——用BinaryFormatter反序列化时碰到未引用程序集里的未知类型,想直接把这些类型解析成null对吧?其实BinaryFormatter本身没提供现成的开关,但我们可以通过自定义SerializationBinder结合ISerializationSurrogate来实现这个需求,思路很清晰,我给你一步步拆解:
核心思路
当BinaryFormatter遇到无法识别的类型时,我们先把它映射到一个自定义的“占位符”类型,再通过序列化代理把这个占位符直接替换成null,全程避免抛出异常。
具体实现步骤
1. 定义占位符类型
先创建一个空的类,用来标记那些无法识别的未知类型:
// 自定义占位符,专门用来承接无法识别的类型 public class UnknownTypePlaceholder { }
2. 自定义SerializationBinder
重写类型绑定逻辑,当找不到目标类型时,返回上面的占位符类型,而不是抛出异常:
public class NullUnknownTypeBinder : SerializationBinder { private readonly Assembly _localAssembly; public NullUnknownTypeBinder(Assembly localAssembly) { _localAssembly = localAssembly; } public override Type BindToType(string assemblyName, string typeName) { try { // 先尝试全局查找类型 var targetType = Type.GetType($"{typeName}, {assemblyName}"); if (targetType != null) return targetType; // 再尝试从当前执行程序集查找 targetType = _localAssembly.GetType(typeName); // 找不到就返回占位符 return targetType ?? typeof(UnknownTypePlaceholder); } catch { // 任何加载失败的情况都返回占位符 return typeof(UnknownTypePlaceholder); } } }
3. 实现ISerializationSurrogate
创建一个代理类,把占位符类型直接转换成null:
public class NullSurrogate : ISerializationSurrogate { // 序列化时不需要处理(我们只关心反序列化逻辑) public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { } // 反序列化时,将占位符替换为null public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { return null; } }
4. 整合并使用
把上面的组件注册到BinaryFormatter里,就可以实现目标功能了:
public static object DeserializeWithNullForUnknownTypes(Stream stream) { var formatter = new BinaryFormatter(); var surrogateSelector = new SurrogateSelector(); // 给占位符类型注册代理,让它反序列化为null surrogateSelector.AddSurrogate( typeof(UnknownTypePlaceholder), new StreamingContext(StreamingContextStates.All), new NullSurrogate() ); formatter.SurrogateSelector = surrogateSelector; // 绑定自定义的类型查找逻辑 formatter.Binder = new NullUnknownTypeBinder(Assembly.GetExecutingAssembly()); try { return formatter.Deserialize(stream); } catch (SerializationException ex) { // 可选:记录日志或者处理其他序列化异常 Console.WriteLine($"反序列化警告:{ex.Message}"); return null; } }
额外注意事项
- 安全性提醒:微软已经将BinaryFormatter标记为不安全的序列化组件,存在远程代码执行的风险。如果是新项目,优先考虑使用System.Text.Json、Protobuf、MessagePack等更安全的序列化库。
- 嵌套类型支持:这个方案支持嵌套的未知类型,因为类型绑定器会递归处理对象结构中的每个类型。
- 自定义扩展:你可以根据自己的需求修改
NullUnknownTypeBinder的查找逻辑,比如添加特定程序集的白名单。
内容的提问来源于stack exchange,提问作者MarkPflug
相关产品推荐
相关产品推荐

