2009-09-21 15 views
12

haciendo referencia a this a una pregunta.¿BinaryFormatter Serialize and Deserialize es seguro?

Puede esto ser reescrita como:

private static BinaryFormatter formatter = new BinaryFormatter(); 

    public static T DeepClone<T>(this T a) 
    { 
     using(MemoryStream stream = new MemoryStream()) 
     { 
      formatter.Serialize(stream, a); 
      stream.Position = 0; 
      return (T)formatter.Deserialize(stream); 
     } 
    } 

lo tanto evitando la construcción (y GC'ing) un nuevo BinaryFormatter para cada llamada?

Esta ruta de código se golpea con mucha frecuencia ya que se trata de nuestra capa de almacenamiento en caché y me gustaría que sea lo más ligera posible.

Gracias.

+1

Un argumento clásico para inmutable;) –

Respuesta

9

Según MSDN:

estáticos públicos (Shared en Visual Basic ) de este tipo son el hilo seguro. Los miembros de instancia no son garantizados para ser seguros para subprocesos.

Por lo tanto, debe sincronizar el acceso a los métodos Serializar/Deserializar.

¿Ha identificado problemas de rendimiento particulares al crear una instancia de serializador local cada vez?


ACTUALIZACIÓN:

que confiaría MSDN porque aunque en algunos casos podemos verificar que los miembros de instancia podría ser seguro para subprocesos, esto no significa que con el próximo Service Pack/actualización/versión del marco de este seguirá siendo el caso.

Mirando con reflector en BinaryFormatter constructor:

public BinaryFormatter() 
{ 
    this.m_typeFormat = FormatterTypeStyle.TypesAlways; 
    this.m_securityLevel = TypeFilterLevel.Full; 
    this.m_surrogates = null; 
    this.m_context = new StreamingContext(StreamingContextStates.All); 
} 

Y StreamingContext constructor:

public StreamingContext(StreamingContextStates state, object additional) 
{ 
    this.m_state = state; 
    this.m_additionalContext = additional; 
} 

Francamente asignación de 6 propiedades (la mayoría de las cuales son enums) debe ser tan rápidos. En mi humilde opinión, la mayor parte del tiempo se gasta en métodos de serialización/deserialización.

+0

Sí, esa es actualmente la ruta caliente (hemos medido). No es el fin del mundo para instanciar un formato para cada solicitud, pero me pregunté si alguien sabía si se trataba de almacenamiento en caché interno, etc. Conocía el aviso en MSDN, pero como probablemente sepa, dice que durante mucho tiempo clases que en realidad son instancia de subprocesos seguros en realidad :) –

6

Puede usar el atributo [ThreadStatic] e inicializar si el valor es nulo. Esto funcionará asumiendo tus hilos de reutilización.

[ThreadStatic] 
private static BinaryFormatter formatter = null; 

public static T DeepClone<T>(this T a) 
    { 
      if(formatter == null) formatter = new BinaryFormatter(); 
      using(MemoryStream stream = new MemoryStream()) 
      { 
        formatter.Serialize(stream, a); 
        stream.Position = 0; 
        return (T)formatter.Deserialize(stream); 
      } 
    } 

Por supuesto, la otra opción es utilizar Relfector.Net de puerta roja y examinar la aplicación del formateador binario. Después de leer el código, debe poder decidir si es seguro para el uso con rosca cruzada; sin embargo, Darin tiene razón en que podría romperse en una versión futura.