2010-05-04 17 views

risposta

19

Ecco un modo hack-ish di farlo senza dover caricare l'intera stringa di uscita in un XmlDocument:

using System; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 

public class Example 
{ 
    public String Name { get; set; } 

    static void Main() 
    { 
     Example example = new Example { Name = "Foo" }; 

     XmlSerializer serializer = new XmlSerializer(typeof(Example)); 

     XmlSerializerNamespaces emptyNamespace = new XmlSerializerNamespaces(); 
     emptyNamespace.Add(String.Empty, String.Empty); 

     StringBuilder output = new StringBuilder(); 

     XmlWriter writer = XmlWriter.Create(output, 
      new XmlWriterSettings { OmitXmlDeclaration = true }); 
     serializer.Serialize(writer, example, emptyNamespace); 

     Console.WriteLine(output.ToString()); 
    } 
} 
+0

+1 - Non penso che sia davvero un hackish. Forse più lavoro di installazione di quanto mi piacerebbe fare. Ma, alla fine, sta dicendo a quale formato deve essere l'output prima che funzioni. Questo non è un hack. Un trucco sarebbe quello di spogliare tutto dopo il fatto ecc. –

+1

Sono d'accordo con Andrew sul fatto che questo è hacker. A meno che non stia facendo qualcosa di sbagliato, tutti i miei elementi hanno l'attributo 'xmlns = ""'. Avrei preferito che non fosse affatto presente. –

+0

** nessuna manipolazione XmlDocument/XmlNode ** – Kiquenet

-2
+2

No. Questo produrrà un documento xml valido che include la dichiarazione XML e i riferimenti dello spazio dei nomi. Voglio solo un frammento. – Emmanuel

+0

IMHO, è meglio cancellare la risposta perché non valida per la domanda. http://stackoverflow.com/help/how-to-answer – Kiquenet

1

Dovreste essere in grado di serializzare proprio come si fa di solito, e quindi utilizzare la proprietà Root dal documento risultante.

Potrebbe essere necessario cancellare prima gli attributi dell'elemento.

+1

+1 Sembra buono per me, ma quello che non ho spiegato nella mia domanda è che preferirei produrre un flusso e non un XmlDocument. – Emmanuel

0

Tra l'altro questo è impressionante. Ho implementato questo codice per semplificare il lavoro con i frammenti xml come classi rapidamente e quindi è sufficiente sostituire il nodo al termine. Questo rende la transizione tra codice e xml ultra-facile.

Prima creare alcuni metodi di estensione.

public static class SerializableFragmentExtensions 
{ 
    public static XElement ToElement(this ISerializableFragment iSerializableFragment) 
    { 
     var serializer = new XmlSerializer(iSerializableFragment.GetType()); 
     var emptyNamespace = new XmlSerializerNamespaces(); 
     emptyNamespace.Add(String.Empty, String.Empty); 

     var output = new StringBuilder(); 

     var writer = XmlWriter.Create(output, 
      new XmlWriterSettings { OmitXmlDeclaration = true }); 
     serializer.Serialize(writer, iSerializableFragment, emptyNamespace); 
     return XElement.Parse(output.ToString(), LoadOptions.None); 
    } 
    public static T ToObject<T>(this XElement xElement) 
    { 
     var serializer = new XmlSerializer(typeof (T)); 
     var reader = xElement.CreateReader(); 
     var obj = (T) serializer.Deserialize(reader); 
     return obj; 
    } 
} 

Avanti implementare l'interfaccia desiderata (interfaccia marker - So che non si dovrebbe, ma penso che questo è il motivo perfetto ad esso.)

public interface ISerializableFragment 
{ 
} 

Ora tutto quello che dovete fare è decorare qualsiasi classe Serializable, si desidera convertire in un frammento XElement, con l'interfaccia.

[Serializable] 
public class SomeSerializableClass : ISerializableFragment 
{ 
    [XmlAttribute] 
    public string SomeData { get; set; } 
} 

Infine testare il codice.

static void Main(string[] args) 
    { 
     var someSerializableClassObj = new SomeSerializableClass() {SomeData = "Testing"}; 
     var element = someSerializableClass.ToElement(); 
     var backToSomeSerializableClassObj = element.ToObject<SomeSerializableClass>(); 
    } 

Grazie ancora per questo codice incredibilmente utile.

+1

C'era un problema che ho subito provato a provare nel mio progetto. Con uno snippet di testo che seguiva esattamente la denominazione corretta, come nell'esempio che ho fornito, il codice funzionava perfettamente. Avevo un nome di classe che non aveva lo stesso nome dell'elemento radice. La risposta è stata semplicemente aggiungendo XmlRootAttribute sulla classe e nominandolo come il nome dell'elemento root in xml. Questo ha funzionato senza difetti. Si può anche essere certi che tutti gli elementi esistenti in xmldocument che non sono espressi nella definizione della classe non interromperanno l'analisi. – jwize