Parcialmente desserialize o XML para objetar
-
20-09-2019 - |
Pergunta
Eu tenho algum XML que eu desapego em um objeto de negócios. Estou usando o xmlSerializer.DeSerialize para fazê -lo. No entanto, quero que um dos XMLELEMENT contido no XML para manter um Xelement.
Isso não pode ser feito diretamente (usando um XMLELEMEMENTATIBUTIVE), pois o Xelement não é serializável. Eu também tentei serializar esse elemento a uma string (em uma tentativa de duas etapas de obter um Xelement), mas isso falhou com o erro:
Elemento do tipo de nó inesperado. O método ReadeLomentString só pode ser chamado em elementos com conteúdo simples ou vazio
Alguma ideia de como isso pode ser feito?
Aqui está um exemplo de XML e o objeto resultante que eu quero:
<Person name="Joe">
<Hobbies>
<Hobby name="Reading" .../>
<Hobby name="Photography" .../>
</Hobbies>
<HomeAddress>
...
</HomeAddress>
</Person>
Objeto:
public class Person
{
[XmlAttribute("Name")]
public string Name {get; set;}
?????
public XElement Hobbies {get; set;}
[XmlElement("HomeAddress")]
public Address HomeAddress {get; set;}
}
As tentativas que não funcionam:
[XmlElement("Hobbies")]
public XElement Hobbies {get; set;}
[XmlElement("Hobbies")]
public string Hobbies {get; set;}
Solução
Para evitar o trabalho árduo de implementar algo como IXmlSerializable
, você pode fazer algo parecido com um passe semi-oculto XmlElement
propriedade; Observe, no entanto, que isso não faz o que você deseja, pois você só pode ter uma raiz XElement
valor (não dois, conforme seu exemplo); Você precisaria de uma lista para fazer isso ...
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);
}
}
Outras dicas
Para ter controle total (juntamente com a responsabilidade total) de como o XML é gerado, você pode que sua classe implemente o System.xml.Serialization.ixmlSerializable Interface e substitua o Readxml e o Writexml. Já tive que fazer isso antes com aulas de dicionário - certifique -se de testar bem, especialmente com propriedades nulas, campos vazios, etc.