2009-03-24 6 views
8

Al construir instancias de XmlSerializer en .NET, los ensamblados para serializar y deserializar el tipo especificado se generan dinámicamente. Este es un proceso lento. La herramienta sgen.exe de Microsoft se puede utilizar para precompilar instancias de XmlSerializer para usarlas más adelante sin generarlas dinámicamente. Desafortunadamente, esto no es posible con las instancias de XmlSerializer que usan XmlAttributeOverrides.Precompila XmlSerializers con XmlAttributeOverrides

¿Hay alguna manera de precompilar estas instancias de XmlSerializer para evitar la generación en tiempo de ejecución?

+0

¿Has llegado a algún otro lado con esto? – Rory

Respuesta

6

Andreas, esto no es un problema de la herramienta sgen en sí, esto se debe a la implementación de XmlSerializer.

Cuando crea una instancia de XmlSerializer, utilizando el constructor con un solo argumento de tipo, va y verifica la caché y busca los ensamblados pregenerados. Pero cuando utiliza el constructor con XmlAttributeOverrides, XmlSerializer no comprueba ningún caché y va generando el ensamblado temporal de inmediato.

Lo más probable es que esto se deba a los cambios bastante radicales en la lógica de serialización que puede lograr utilizando el argumento XmlAttributeOverrides, que las herramientas como sgen no pueden "prever" en tiempo de compilación.

Si necesita que las cosas se compilen previamente, [suspiro] debe evitar las XmlAttributeOverrides. Si esto no es posible, intente crear las instancias de XmlSerializer requeridas antes de tiempo, tal vez en un hilo de fondo.

sólo por su interés, aquí está el código para el constructor por defecto (caché de cheques y trata de encontrar un conjunto de pre-generado):

public XmlSerializer(Type type, string defaultNamespace) 
{ 
    this.events = new XmlDeserializationEvents(); 
    if (type == null) 
    { 
     throw new ArgumentNullException("type"); 
    } 
    this.mapping = GetKnownMapping(type, defaultNamespace); 
    if (this.mapping != null) 
    { 
     this.primitiveType = type; 
    } 
    else 
    { 
     this.tempAssembly = cache[defaultNamespace, type]; 
     if (this.tempAssembly == null) 
     { 
      lock (cache) 
      { 
       this.tempAssembly = cache[defaultNamespace, type]; 
       if (this.tempAssembly == null) 
       { 
        XmlSerializerImplementation implementation; 
        Assembly assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out implementation); 
        if (assembly == null) 
        { 
         this.mapping = new XmlReflectionImporter(defaultNamespace).ImportTypeMapping(type, null, defaultNamespace); 
         this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace); 
        } 
        else 
        { 
         this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); 
         this.tempAssembly = new TempAssembly(new XmlMapping[] { this.mapping }, assembly, implementation); 
        } 
       } 
       cache.Add(defaultNamespace, type, this.tempAssembly); 
      } 
     } 
     if (this.mapping == null) 
     { 
      this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); 
     } 
    } 
} 

Y aquí es el constructor se utiliza con XmlAttributeOverrides (siempre genera serialización montaje):

public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location, Evidence evidence) 
{ 
    this.events = new XmlDeserializationEvents(); 
    if (type == null) 
    { 
     throw new ArgumentNullException("type"); 
    } 
    XmlReflectionImporter importer = new XmlReflectionImporter(overrides, defaultNamespace); 
    for (int i = 0; i < extraTypes.Length; i++) 
    { 
     importer.IncludeType(extraTypes[i]); 
    } 
    this.mapping = importer.ImportTypeMapping(type, root, defaultNamespace); 
    if (location != null) 
    { 
     this.DemandForUserLocation(); 
    } 
    this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence); 
} 
+0

Ah, me he encontrado con este mismo problema. Lamentablemente, no puedo usar la creación dinámica de ensamblajes de serialización porque no puedo iniciar csc.exe (estoy corriendo desde el modo protegido Internet Explorer). ¿Alguna sugerencia? Estoy pensando que podría capturar el archivo .cs temporal creado por XmlSerializer, incluirlo en mi compilación y usarlo en lugar de XmlSerializer directamente. Suena sucio pero ¿alguna otra idea? Mi qn aquí: http://stackoverflow.com/questions/7333689/generating-an-xml-serialization-assembly-for-a-custom-xmlserializer – Rory

Cuestiones relacionadas