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
Antwort
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.
Uri Klasse implementiert ISerializable Schnittstelle, so dass es in der Lage sein sollte, Serialisierung/Deserialisierung zu kümmern.
Hmmm, vielleicht eine 3.5 Sache? Ich bekomme eine Ausnahme, dass es keinen Standardkonstruktor gibt, wenn ich in 2 serialisiere.0 – Jeremy
Das ist für * binäre * Serialisierung; die Frage (siehe Tags) ist über * xml * Serialisierung –
Uri ist bereits Serializeable, also glaube ich nicht, dass Sie irgendetwas tun müssen.
http://msdn.microsoft.com/en-us/library/system.uri(VS.80).aspx
Die Tags vorschlagen xmlserializer, so dass (allein) nicht viel tun –
Implementieren und IDeserializationCallback und das Feld auf Ihrem eigenen verwenden.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ideserializationcallback.aspx
Die Tags vorschlagen xmlserializer - die diese nicht unterstützt –
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)
Hinweis: Es gibt eine kleine hitch hier. Die Serialisierung funktioniert, aber die Deserialisierung schlägt fehl. –
@SriwanthaAttanayake Ich denke das hängt vom Uri ab. – Aelphaeis
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>
Die Tags XmlSerializer vorschlagen; Eigentlich brauchst du [Serializable] dafür nicht - der Typ muss nur öffentlich sein. –