我正在寻找有关如何检测运行时平台以公开 Microsoft .Net 二进制反序列化失败的源类型的见解。
当使用BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine)
并且当前二进制文件中不存在其中一种类型时; .Net 不会抛出错误,而是插入对象 [TypeLoadExceptionHolder]
。特别是对于集合而言,这不会立即造成问题。
随后,当集合被序列化以在应用程序层之间传输时;平台收到“序列化失败”,因为[TypeLoadExceptionHolder]
无法序列化。因此,产生的错误对于实际提供有关导致问题的源类型的线索是无用的。现在,我们正在寻找(时间很糟糕),看看哪个开发人员(数百个)向百万行平台添加了新类型。
由于用于支持平台 session 缓存的序列化流,此问题经常发生。代码的部署相当频繁且以增量方式进行。在部署窗口期间,客户页面请求可以在新旧版本的代码库之间切换。不小心引入新类型会导致旧版本的页面请求崩溃。
任何关于提供运行时丰富的错误/陷阱的想法将不胜感激。
<小时/>(SerializationException)
Type 'System.Runtime.Serialization.TypeLoadExceptionHolder' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
- at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
- at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
- at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
最佳答案
嗯,您可以采取的一种方法是使用自定义 SerializationBinder
覆盖 BindToType
并在反序列化期间检查类型名称。
根据您想要完成的任务,当您识别未知类型时,您可以:
引发异常(悲观):尽早发现问题,并可以通过自定义消息或异常轻松识别类型。
记录类型名称(乐观):如果存在未知类型正常的情况,日志记录将提供诊断异常(如果异常在序列化过程中稍后发生)所需的详细信息。
您还可以根据类型名称的特征选择不同的方法(即,该类型是否是您的应用程序的一部分或第三方库的一部分)。
反序列化期间创建的 TypeLoadExceptionHolder
实例确实包含一个非公共(public)成员 TypeName
,其中包含无法解析的类型的名称。但是,该实例无法从您稍后遇到的 SerializationException
中获得,即使如此,该值也只能通过受信任上下文中的反射来获得。
public class CustomSerializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type t = Type.GetType(string.Concat(typeName, ", ", assemblyName));
if (t == null)
{
throw new SerializationException(string.Format("Type {0} from assembly {1} could not be bound.", typeName, assemblyName));
}
return t;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
base.BindToName(serializedType, out assemblyName, out typeName);
}
}
...
BinaryFormatter.Binder = new CustomSerializationBinder();
关于.Net 二进制反序列化运行时平台的故障检测/取证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3246082/