2011-11-16 5 views
5

J'ai la pièce de code suivanteComment rendre la désérialisation XML plus rapide?

public static object XmlDeserialize(string xml, Type objType) 
{ 
    StringReader stream = null; 
    XmlTextReader reader = null; 
    try 
    { 
     XmlSerializer serializer = new XmlSerializer(objType); 
     stream = new StringReader(xml); // Read xml data 
     reader = new XmlTextReader(stream); // Create reader 
     return serializer.Deserialize(reader); 
    } 
    finally 
    { 
     if(stream != null) stream.Close(); 
     if(reader != null) reader.Close(); 
    } 
} 

L'objet lui-même a été généré par xsd.exe et ressemble un peu à ceci:

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] 
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] 
public partial class MyObject { 

    private DemographicsCriteriaStateStartAge[] startAgesField; 

    private DemographicsCriteriaStateEndAge[] endAgesField; 

    private DemographicsCriteriaStateFilter[] selectedFiltersField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlArrayItemAttribute("StartAge", IsNullable=false)] 
    public DemographicsCriteriaStateStartAge[] StartAges { 
     get { 
      return this.startAgesField; 
     } 
     set { 
      this.startAgesField = value; 
     } 
    } 
    ... 

La méthode est généralement appelée comme ceci:

var obj = (MyObject) XmlDeserialize(someXmlString, typeof(MyObject)); 

La ligne de code suivante prend toujours une bonne partie du temps (par rapport à tout le reste):

XmlSerializer serializer = new XmlSerializer(objType); 

Ce qui se passe ici, par ex. compile-t-il un assemblage de désérialisation en arrière-plan? Pourquoi le problème de performance? Que puis-je faire pour améliorer ce problème de performance?

+0

Une note de côté, au lieu de 'essayer ... enfin, vous auriez pu utiliser 'using'. – svick

Répondre

5

Oui, il génère dynamiquement un assembly de sérialisation au moment de l'exécution. Vous pouvez modifier ce comportement dans Visual Studio. Accédez aux propriétés du projet et à la section de construction. Il existe un paramètre pour "Générer des assemblages de sérialisation" défini sur true. Cela va générer un fichier comme YourProject.XmlSerialiser.dll lorsque vous compilez et arrêter ce goulot d'étranglement à l'exécution. Une exception à noter, cependant, est que ce paramètre s'applique uniquement aux types de proxy (par exemple, proxys de service Web, etc.). Pour forcer réellement Visual Studio 2010 à générer des assemblages de sérialisation pour les types réguliers, il faut soit jouer avec le fichier projet (.csproj) et supprimer/proxytypes de l'appel Sgen soit générer une étape post-construction pour appeler manuellement sgen.exe sur l'assembly.

+0

J'ai un tas d'assemblées. Dois-je définir le paramètre pour l'EXE principal ou pour les assemblys DLL dépendants? Btw, j'ai fait tout cela et n'ai vu aucun fichier YourProject.XmlSerialiser.dll dans bin/debug. – AngryHacker

+0

Je l'ai seulement utilisé avec des proxies Web et il semble y avoir un certain débat quant à savoir s'il y a un bug ici http://connect.microsoft.com/VisualStudio/feedback/details/123088/project-does-not-generate- sérialisation-assemblage-même-quand-spécifiquement-dit-à-faire-ainsi. Pour un contrôle plus fin, regardez l'outil exe documenté ici http://msdn.microsoft.com/en-us/library/bk3w6240(v=vs.80).aspx –

+0

Je pense que vous aurez besoin d'un assemblage de sérialisation par assemblage normal . –

4

Essayez la mise en cache l'instance du XmlSerializer pour chaque type au niveau de la classe afin que vous n'avez pas à le recréer à chaque fois si le même type est utilisé:

class Foo 
{ 
    private static Dictionary<Type, XmlSerializer> xmls = new Dictionary<Type, XmlSerializer>(); 

    // ... 

    public static object XmlDeserialize(string xml, Type objType) 
    { 
     StringReader stream = null; 
     XmlTextReader reader = null; 
     try 
     { 
      XmlSerializer serializer; 
      if(xmls.Contains(objType)) { 
       serializer = xmls[objType]; 
      } 
      else { 
       serializer = new XmlSerializer(objType); 
       xmls[objType] = serializer; 
      }   

      stream = new StringReader(xml); // Read xml data 
      reader = new XmlTextReader(stream); // Create reader 
      return serializer.Deserialize(reader); 
     } 
     finally 
     { 
      if(stream != null) stream.Close(); 
      if(reader != null) reader.Close(); 
     } 
    } 
} 
+0

C'était ma réponse quand j'ai découvert combien de temps il faut pour construire un XmlSerializer même pour une classe simple. Mais je pense que la mise en cache se passe de toute façon dans la classe XmlSerializer, car la seconde fois que vous créez un XmlSerializer pour un type donné, cela ne prend pas presque autant de temps. – markmuetz

Questions connexes