2009-09-21 12 views
12

Référencement this répondre à une question.BinaryFormatter Sérialiser et désérialiser le thread est-il sécurisé?

peut-il être réécrite comme:

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); 
     } 
    } 

Évitant la construction (et GC'ing) un nouveau BinaryFormatter pour chaque appel?

Ce chemin de code est très fréquemment touché car il implique notre couche de mise en cache et je voudrais le rendre aussi léger que possible.

Merci.

+1

Un argument classique pour immutable;) –

Répondre

9

Selon MSDN:

Tout public static (Shared en Visual Basic) de ce type sont thread sûr. Tous les membres d'instance ne sont pas garanti être thread-safe.

Vous devez donc synchroniser l'accès aux méthodes de sérialisation/désérialisation.

Avez-vous identifié des problèmes de performances particuliers en créant une instance de sérialiseur locale à chaque fois?


MISE À JOUR:

Je confierais MSDN parce que même si, dans certains cas, nous pouvons vérifier que les membres de l'instance pourrait être thread-safe cela ne signifie pas que le prochain service pack/mise à jour/version cadre de cette continuera à être le cas.

Vous cherchez avec réflecteur au constructeur BinaryFormatter:

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

Et constructeur StreamingContext:

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

6 propriétés tout à fait franchement (assignant dont la plupart sont enums) devrait être aveuglante rapide. À mon humble avis la plupart du temps serait passé dans Serialize/Deserialize méthodes.

+0

Oui c'est actuellement le chemin chaud (nous avons mesuré). Ce n'est pas la fin du monde pour instancier un formaté pour chaque requête, mais je me demandais si quelqu'un savait s'il faisait la mise en cache interne etc. Je connaissais l'avis sur MSDN, mais comme vous le savez probablement, il dit que pour beaucoup de les classes qui sont réellement des threads d'instance en toute sécurité :) –

6

Vous pouvez utiliser l'attribut [ThreadStatic] et initialiser si la valeur est null. Cela fonctionnera en supposant que vous réutilisez des threads.

[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); 
      } 
    } 

Bien sûr, l'autre option est d'utiliser Relfector.Net de Red Gate et examiner la mise en œuvre du binaire formatter. Après avoir lu le code, vous devriez être en mesure de décider s'il est sécuritaire d'utiliser un filetage croisé; Cependant, Darin a raison de dire qu'il pourrait casser dans une future version.

Questions connexes