2009-06-24 1 views
16

Ich habe eine Klasse, die ich als Serializable markiert, mit einer Uri-Eigenschaft. Wie kann ich den Uri serialisieren/deserialisieren, ohne die Eigenschaft vom Typ string zu machen?Wie (xml) serialisieren Sie eine uri

+1

Die Tags XmlSerializer vorschlagen; Eigentlich brauchst du [Serializable] dafür nicht - der Typ muss nur öffentlich sein. –

Antwort

12

Basierend auf einer der Antworten für how to serialize TimeSpan landete ich mit dieser, die für mich ganz gut funktioniert und erfordert nicht die zusätzliche Eigenschaft :

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

Dann können Sie es wie folgt

public class Settings 
{ 
    public XmlUri Uri { get; set; } 
} 

... 
var s = new Settings { Uri = new Uri("http://www.example.com") }; 

verwenden und es wird schön serialisiert und deserialisiert.

Hinweis: Der Trick mit dem XmlElement(Type = typeof(...))-Attribut, wie in einer anderen Antwort in der obigen verknüpften Frage angegeben, kann nicht verwendet werden, da die XmlSerializer zuerst auf dem ursprünglichen Typ nach einem leeren Standardkonstruktor sucht.

0

Uri Klasse implementiert ISerializable Schnittstelle, so dass es in der Lage sein sollte, Serialisierung/Deserialisierung zu kümmern.

+0

Hmmm, vielleicht eine 3.5 Sache? Ich bekomme eine Ausnahme, dass es keinen Standardkonstruktor gibt, wenn ich in 2 serialisiere.0 – Jeremy

+4

Das ist für * binäre * Serialisierung; die Frage (siehe Tags) ist über * xml * Serialisierung –

32

Mit xml Serializer, Sie sind beschränkt - es ist nicht so vielseitig wie (sagen wir) einige der BinaryFormatter/ISerializable Optionen ist. Ein häufiger Trick ist eine zweite Eigenschaft für die Serialisierung haben:

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

Die beiden durchsuchbaren Attribute verstecken sie aus dem Blickfeld (aber es muss auf die öffentliche API für XmlSerializer sein, es zu benutzen). Die XmlIgnore sagt es nicht zu versuchen, die Uri; und die [XmlAttribute(...)] (oder [XmlElement(...)]) sagt ihm, UriString beim (De) Serialisierung umzubenennen.

(beachten Sie, dass EditorBrowsable nur außerhalb der Baugruppe Code gilt die Art erklärt)

+0

Hinweis: Es gibt eine kleine hitch hier. Die Serialisierung funktioniert, aber die Deserialisierung schlägt fehl. –

+0

@SriwanthaAttanayake Ich denke das hängt vom Uri ab. – Aelphaeis

1

Für andere, die diese Frage gefunden haben und denen die Lösungen nicht gefallen haben, gibt es noch eine flexiblere und leistungsfähigere Lösung. Es ist die Implementierung IXmlSerializable-Schnittstelle. Das ist schwieriger, aber es ist es wert. Sie können ein beliebiges XML erstellen, das Sie möchten. Das einfachste Beispiel ist:

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

Und Sie so etwas wie dies in xml erhalten:

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