2009-03-24 7 views
8

Beim Erstellen von XmlSerializer-Instanzen in .NET werden Assemblys zum Serialisieren und Deserialisieren des angegebenen Typs dynamisch generiert. Dies ist ein zeitaufwendiger Prozess. Mit dem Tool sgen.exe von Microsoft können XmlSerializer-Instanzen vorkompiliert werden, um sie später zu verwenden, ohne sie dynamisch zu generieren. Leider ist dies nicht möglich mit XmlSerializer-Instanzen, die XmlAttributeOverrides verwenden.Vorkompilierte XmlSerializers mit XmlAttributeOverrides

Gibt es eine Möglichkeit, diese XmlSerializer-Instanzen vorkompilieren, um die Generierung zur Laufzeit zu vermeiden?

+0

Haben Sie damit weiter kommen? – Rory

Antwort

6

Andreas, das ist kein Problem des Sgen-Tools selbst, das liegt an der XmlSerializer-Implementierung.

Wenn Sie eine Instanz von XmlSerializer mithilfe des Konstruktors mit nur einem Type-Argument erstellen, geht es und überprüft den Cache und sucht nach den vorgenerierten Assemblys. Wenn Sie jedoch den Konstruktor mit XmlAttributeOverrides verwenden, überprüft XmlSerializer keine Caches und generiert sofort die temporäre Assembly.

Wahrscheinlich liegt das an den ziemlich radikalen Änderungen in der Serialisierungslogik, die Sie mit dem XmlAttributeOverrides-Argument erreichen können, das in der Kompilierzeit von Tools wie sgen nicht "vorausgesehen" werden kann.

Wenn Sie Dinge vorkompiliert haben müssen, müssen Sie die XmlAttributeOverrides vermeiden. Wenn dies nicht möglich ist, erstellen Sie die erforderlichen XmlSerializer-Instanzen im Voraus, möglicherweise in einem Hintergrundthread.

Gerade für Ihr Interesse, hier ist der Code für den Standard-Konstruktor (prüft Cache und versucht, eine bereits generierte Assembly zu finden):

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

Und hier ist der Konstruktor mit XmlAttributeOverrides verwendet (immer erzeugt Serialisierung Assembly):

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, ich habe das gleiche Problem angetroffen. Leider kann ich die dynamische Erstellung von Serialisierungsassemblys nicht verwenden, da ich csc.exe nicht starten kann (wird im Internet Explorer im geschützten Modus ausgeführt). Irgendwelche Vorschläge? Ich denke, dass ich die temporäre .cs-Datei erfassen konnte, die von XmlSerializer erstellt wird, diese in meinem Build einfügte und diese direkt anstelle von XmlSerializer verwendete. Klingt chaotisch, aber andere Ideen? Mein qn hier: http://stackoverflow.com/questions/7333689/generating-an-xml-serialization-assembly-for-a-custom-xmlserializer – Rory