Parzialmente deserializzare XML per oggetto
-
20-09-2019 - |
Domanda
Ho qualche XML che ho deserializzare in un oggetto di business. Sto usando XmlSerializer.Deserialize a farlo. Tuttavia, voglio uno dei XmlElement contenuta nel XML di stare una XElement.
Non può essere fatto direttamente (utilizzando un XmlElementAttribute) poiché XElement non è Serializable. Ho anche provato a serializzare quell'elemento in una stringa (in due fasi tentano di ottenere un XElement), ma che non è riuscita con l'errore:
inaspettato tipo nodo elemento. Metodo readelementstring può essere solo invitato elementi con semplice o contenuto vuoto
Qualsiasi idea di come si può fare?
Ecco un esempio di XML e l'oggetto risultante voglio:
<Person name="Joe">
<Hobbies>
<Hobby name="Reading" .../>
<Hobby name="Photography" .../>
</Hobbies>
<HomeAddress>
...
</HomeAddress>
</Person>
Oggetto:
public class Person
{
[XmlAttribute("Name")]
public string Name {get; set;}
?????
public XElement Hobbies {get; set;}
[XmlElement("HomeAddress")]
public Address HomeAddress {get; set;}
}
I tentativi che non funzionano:
[XmlElement("Hobbies")]
public XElement Hobbies {get; set;}
[XmlElement("Hobbies")]
public string Hobbies {get; set;}
Soluzione
Per evitare il duro lavoro di attuare qualcosa di simile IXmlSerializable
, si potrebbe fare qualcosa sulla falsariga di un semi-nascosta pass-thru proprietà XmlElement
; notare, tuttavia, che questo non abbastanza fare quello che vuoi perché si può avere un solo valore XElement
root (non due, secondo il vostro esempio); si avrebbe bisogno di una lista di farlo ...
using System;
using System.ComponentModel;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
public class Person
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlIgnore]
public XElement Hobbies { get; set; }
[XmlElement("Hobbies")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public XmlElement HobbiesSerialized
{
get
{
XElement hobbies = Hobbies;
if(hobbies == null) return null;
XmlDocument doc = new XmlDocument();
doc.LoadXml(hobbies.ToString());
return doc.DocumentElement;
}
set
{
Hobbies = value == null ? null
: XElement.Parse(value.OuterXml);
}
}
[XmlElement("HomeAddress")]
public Address HomeAddress { get; set; }
}
public class Address { }
static class Progmam
{
static void Main()
{
var p = new Person { Hobbies = new XElement("xml", new XAttribute("hi","there")) };
var ser = new XmlSerializer(p.GetType());
ser.Serialize(Console.Out, p);
}
}
Altri suggerimenti
Per avere il pieno controllo (insieme con piena responsabilità) per come l'XML è generato si può avere la classe implementi l'interfaccia System.Xml.Serialization.IXmlSerializable, e ignorare ReadXml e WriteXml. Ho avuto a che fare prima con le classi del dizionario - essere sicuri di testare a fondo, in particolare con le proprietà null, campi vuoti, etc
.