2010-07-14 19 views
12

Estoy buscando información sobre cómo instrumentar una plataforma de tiempo de ejecución para exponer el tipo de fuente de una falla de deserialización binaria de Microsoft .Net..Net Binary Deserialization Detección de fallas/forensics para plataforma de tiempo de ejecución

Al usar BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine) y uno de los tipos no existe en los binarios actuales; en lugar de arrojar un error, .Net inserta el objeto [TypeLoadExceptionHolder]. Particularmente para las colecciones, esto no causa un problema inmediato.

Posteriormente cuando la colección se serializa para transmisión entre niveles de aplicación; la plataforma recibe una 'falla de serialización' porque [TypeLoadExceptionHolder] no se puede serializar. Entonces, el error resultante es inútil para proporcionar pistas sobre el tipo de fuente que causó el problema. Ahora la búsqueda (succión de tiempo) está activada para ver qué desarrollador (de cientos) agregó un nuevo tipo a una plataforma de un millón de líneas.

Este problema ocurre con cierta frecuencia debido a la secuencia de serialización utilizada para admitir la sesión de la plataforma. El código se implementa con bastante frecuencia y de forma incremental. Las solicitudes de página del cliente pueden rebotar entre versiones antiguas y nuevas de la base de código durante la ventana de implementación. La introducción descuidada de un nuevo tipo hará que las solicitudes de página en la versión anterior exploten.

Se agradecerá cualquier idea sobre la provisión de error/trampa ricos en tiempo de ejecución.


(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) 

Respuesta

4

Bueno, un enfoque que podría tomar es utilizar una costumbre SerializationBinder que anula BindToType y comprueba el nombre de tipo durante la deserialización.

Dependiendo de lo que desea lograr, al identificar un tipo desconocido que bien podría:

  • lanzar una excepción (pesimista): Coger el tema desde el principio y puede fácilmente la identidad del tipo con un mensaje personalizado o una excepción.

  • Registre el Nombre del tipo (Optimista): Si hay escenarios en los que los tipos desconocidos son correctos, el registro proporcionará los detalles necesarios para diagnosticar excepciones si se producen más adelante durante la serialización.

También se puede seleccionar un enfoque diferente dependiendo de las características del nombre de tipo (es decir, si el tipo parece ser parte de su aplicación o parte de una biblioteca tercera parte).

La instancia TypeLoadExceptionHolder creada durante la deserialización contiene un miembro no público TypeName que contiene el nombre del tipo que no se pudo resolver. Sin embargo, la instancia no está disponible en el SerializationException que encontrará más adelante, y aun así, el valor solo estará disponible a través de la reflexión en contextos confiables.

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(); 
Cuestiones relacionadas