2011-11-16 23 views
5

tengo el siguiente fragmento de código¿Cómo hacer que la deserialización XML sea más rápida?

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

El objeto en sí mismo se ha generado a través de xsd.exe y se ve algo así como esto:

/// <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; 
     } 
    } 
    ... 

El método se suele llamar así:

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

La siguiente línea de código siempre toma una gran cantidad de tiempo (en comparación con todo lo demás):

XmlSerializer serializer = new XmlSerializer(objType); 

¿Qué está pasando aquí, p. está compilando una asamblea de deserialización en el fondo? ¿Por qué el problema de rendimiento?

¿Qué puedo hacer para mejorar este problema de rendimiento?

+0

Una nota al margen, en lugar de 'tratar ... finalmente', podrías haber usado 'using'. – svick

Respuesta

5

Sí, está generando dinámicamente un conjunto de serialización en tiempo de ejecución. Puede cambiar este comportamiento en Visual Studio. Ve a las propiedades del proyecto y la sección de compilación. Hay una configuración para "Generar ensamblajes de serialización" configurarlo en verdadero. Esto generará un archivo como YourProject.XmlSerialiser.dll cuando compile y detendrá este cuello de botella en tiempo de ejecución.

Una excepción a tener en cuenta, sin embargo, es que esta configuración solo se aplica a los tipos de proxy (por ejemplo, proxies de servicio web y similares). Para forzar realmente Visual Studio 2010 a generar ensamblajes de serialización para tipos normales, uno debe desordenar con el archivo de proyecto (.csproj) y eliminar/proxytypes de la llamada Sgen o generar un paso posterior a la construcción para llamar manualmente a sgen.exe en el ensamblado.

+0

Tengo un montón de conjuntos. ¿Establezco la configuración para el EXE principal o para los ensamblados DLL dependientes? Por cierto, he hecho todo esto y no he visto ningún archivo YourProject.XmlSerialiser.dll en bin/debug. – AngryHacker

+0

Solo lo he usado con proxys web y parece haber cierto debate sobre si hay algún error aquí http://connect.microsoft.com/VisualStudio/feedback/details/123088/project-does-not-generate- serialization-assembly-even-when-specific-told-to-do-so. Para un control más detallado mire la herramienta exe documentada aquí http://msdn.microsoft.com/en-us/library/bk3w6240(v=vs.vvs.80).aspx –

+0

Creo que necesitará un ensamblaje de serialización por ensamblado normal . –

4

Trate almacenamiento en caché de la instancia de la XmlSerializer para cada tipo a nivel de clase por lo que no tiene que volver a crear cada vez que si se utiliza el mismo tipo:

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

Esta fue mi respuesta cuando descubrí cuánto tiempo lleva construir un XmlSerializer incluso para una clase simple. Pero creo que el almacenamiento en caché ocurre en la clase XmlSerializer de todos modos, porque la segunda vez que creas un XmlSerializer para un tipo dado, no toma casi tanto tiempo. – markmuetz

Cuestiones relacionadas