我有一个我标记为Serializable的类,带有Uri属性。如何在不创建string类型属性的情况下让Uri序列化/反序列化?
答案 0 :(得分:32)
使用xml序列化程序,你是有限的 - 它不像(例如)一些binaryformatter / ISerializable
选项那样通用。一个常见的技巧是获得序列化的第二个属性:
[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);}
}
两个可浏览的属性将其隐藏在视图中(但它需要在XmlSerializer
的公共API上才能使用它)。 XmlIgnore
告诉它不要尝试Uri
;并且[XmlAttribute(...)]
(或[XmlElement(...)]
)告诉它在(de)序列化时重命名UriString
。
(请注意,EditorBrowsable
仅适用于声明类型的程序集之外的代码)
答案 1 :(得分:12)
根据how to serialize TimeSpan
的答案之一,我最终得到了这个,对我来说效果很好,并且不需要额外的属性:
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());
}
}
然后你可以像这样使用它
public class Settings
{
public XmlUri Uri { get; set; }
}
...
var s = new Settings { Uri = new Uri("http://www.example.com") };
它将很好地序列化和反序列化。
注意:不能使用上面链接问题中另一个答案中给出的XmlElement(Type = typeof(...))
属性的技巧,因为XmlSerializer
首先检查原始类型的空默认构造函数。
答案 2 :(得分:1)
对于发现此问题且不喜欢解决方案的其他人,还有另一种更灵活,更强大的解决方案。它的实现是IXmlSerializable接口。这更难,但值得。您可以创建任何您想要的xml。最简单的例子是:
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();
}
}
}
你在xml中得到这样的东西:
<PriceContainer Code="314" Model="PP500" Name="NuTone PurePower PP500 Power Unit">
<Image Src="http://www.thinkvacuums.com/images/nutone-pp500-activac.jpg" />
</PriceContainer>
答案 3 :(得分:0)
Uri类实现了ISerializable接口,因此它应该能够处理序列化/反序列化。
答案 4 :(得分:0)
实现和IDeserializationCallback并自己使用该字段。
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ideserializationcallback.aspx
答案 5 :(得分:-1)
Uri已经是Serializable,所以我不相信你必须做任何事情。
http://msdn.microsoft.com/en-us/library/system.uri(VS.80).aspx