2009-03-24 7 views
8

Quando si creano istanze XmlSerializer in .NET, gli assembly per serializzare e deserializzare il tipo specificato vengono generati dinamicamente. Questo è un processo che richiede tempo. Lo strumento sgen.exe di Microsoft può essere utilizzato per precompilare le istanze di XmlSerializer per utilizzarle in seguito senza generarle dinamicamente. Sfortunatamente questo non è possibile con le istanze di XmlSerializer che usano XmlAttributeOverrides.Precompilare XmlSerializers con XmlAttributeOverrides

C'è un modo per precompilare queste istanze di XmlSerializer per evitare la generazione in fase di esecuzione?

+0

Sei andato oltre? – Rory

risposta

6

Andreas, questo non è un problema dello strumento sgen stesso, questo è dovuto all'implementazione di XmlSerializer.

Quando si crea un'istanza di XmlSerializer, utilizzando il costruttore con un solo argomento Type, esso va, controlla la cache e cerca gli assembly pre-generati. Ma quando si utilizza il costruttore con XmlAttributeOverrides, XmlSerializer non controlla alcuna cache e genera subito l'assembly temporaneo.

Molto probabilmente, è a causa delle modifiche abbastanza radicali nella logica di serializzazione che è possibile ottenere utilizzando l'argomento XmlAttributeOverrides, che non può essere "previsto" in fase di compilazione da strumenti come sgen.

Se è necessario disporre le cose precompilate, si deve evitare [XmlAttributeOverrides. Se ciò non è possibile, provare a creare le istanze di XmlSerializer richieste in anticipo, magari in un thread in background.

Proprio per il vostro interesse, qui è il codice per il costruttore di default (cache controlli e cerca di trovare un pre-generata di montaggio):

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

E qui è il costruttore utilizzato con XmlAttributeOverrides (genera sempre la serializzazione montaggio):

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, ho riscontrato lo stesso problema. Sfortunatamente non è possibile utilizzare la creazione dinamica di assembly di serializzazione perché non riesco ad avviare csc.exe (sto eseguendo da Internet Explorer in modalità protetta). Eventuali suggerimenti? Sto pensando di poter acquisire il file .cs temporaneo creato da XmlSerializer, includerlo nella mia build e utilizzarlo direttamente al posto di XmlSerializer. Sembra disordinato ma qualche altra idea? Il mio qn qui: http://stackoverflow.com/questions/7333689/generating-an-xml-serialization-assembly-for-a-custom-xmlserializer – Rory

Problemi correlati