sharp serialize serializar deserialize deserializar c# .net xml-serialization

serializar - serializer c#



Cómo(xml) serializar un uri (6)

Con el serializador xml, está limitado: no es tan versátil como (digamos) algunas de las opciones de ISerializable binario / ISerializable . Un truco frecuente es tener una segunda propiedad para la serialización:

[XmlIgnore] public Uri Uri {get;set;} [XmlAttribute("uri")] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public string UriString { get {return Uri == null ? null : Uri.ToString();} set {Uri = value == null ? null : new Uri(value);} }

Los dos atributos navegables lo ocultan de la vista (pero debe estar en la API pública para que XmlSerializer use). El XmlIgnore le dice que no pruebe el Uri ; y el [XmlAttribute(...)] (o [XmlElement(...)] le dice que cambie el nombre de UriString cuando (des) lo serializa.

(tenga en cuenta que EditorBrowsable solo se aplica al código fuera del ensamblaje que declara el tipo)

Tengo una clase que he marcado como Serializable, con una propiedad Uri. ¿Cómo puedo hacer que Uri se serialice / deserialice sin hacer la propiedad de tipo cadena?



Para otros que encontraron esta pregunta y no les gustaron las soluciones, existe otra solución más flexible y poderosa. Es la implementación de la interfaz IXmlSerializable. Esto es más difícil, pero vale la pena. Puedes crear cualquier xml que quieras. El ejemplo más simple es:

public class Product : IXmlSerializable { public string Code { get; set; } public string Model { get; set; } public string Name { get; set; } public Uri ImageUri { get; set; } public virtual System.Xml.Schema.XmlSchema GetSchema() { throw new NotImplementedException(); } public virtual void ReadXml(XmlReader reader) { reader.MoveToContent(); Code = reader.GetAttribute("Code"); Model = reader.GetAttribute("Model"); Name = reader.GetAttribute("Name"); if (reader.ReadToDescendant("Image") && reader.HasAttributes) ImageUri = new Uri(reader.GetAttribute("Src")); } public virtual void WriteXml(XmlWriter writer) { writer.WriteAttributeString("Code", Code); writer.WriteAttributeString("Model", Model); writer.WriteAttributeString("Name", Name); if (ImageUri != null) { writer.WriteStartElement("Image"); writer.WriteAttributeString("Src", ImageUri.AbsoluteUri); writer.WriteEndElement(); } } }

Y obtienes algo como esto en xml:

<PriceContainer Code="314" Model="PP500" Name="NuTone PurePower PP500 Power Unit"> <Image Src="http://www.thinkvacuums.com/images/nutone-pp500-activac.jpg" /> </PriceContainer>



Uri clase Uri implementa la Interfaz ISerializable por lo que debería ser capaz de cuidar la serialización / deserialización.


Basándome en una de las respuestas sobre cómo serializar TimeSpan , terminé con esto, que funciona bastante bien para mí y no requiere la propiedad adicional:

public class XmlUri : IXmlSerializable { private Uri _Value; public XmlUri() { } public XmlUri(Uri source) { _Value = source; } public static implicit operator Uri(XmlUri o) { return o == null ? null : o._Value; } public static implicit operator XmlUri(Uri o) { return o == null ? null : new XmlUri(o); } public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { _Value = new Uri(reader.ReadElementContentAsString()); } public void WriteXml(XmlWriter writer) { writer.WriteValue(_Value.ToString()); } }

Entonces puedes usarlo así

public class Settings { public XmlUri Uri { get; set; } } ... var s = new Settings { Uri = new Uri("http://www.example.com") };

Y bien serializará y deserializará.

Nota: No se puede usar el truco con el XmlElement(Type = typeof(...)) como se indica en otra respuesta en la pregunta vinculada anterior, ya que el XmlSerializer busca XmlSerializer un constructor predeterminado vacío en el tipo original.