Как (xml) сериализовать uri
У меня есть класс, который я обозначил как Serializable, с свойством Uri. Как я могу получить Uri для сериализации/десериализации без создания свойства строки типа?
Ответы
Ответ 1
Основываясь на одном из ответов как сериализовать 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
С помощью 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);}
}
Два атрибута, доступные для просмотра, скрывают его от представления (но он должен быть включен в общедоступный API для XmlSerializer
, чтобы использовать его). XmlIgnore
говорит, что не попробовать Uri
; и [XmlAttribute(...)]
(или [XmlElement(...)]
) сообщает ему переименовать UriString
, когда (de) сериализует его.
(обратите внимание, что EditorBrowsable
применяется только к коду вне сборки, объявляющему тип)
Ответ 3
Для других, кто нашел этот вопрос и кому не понравились решения, существует еще одно гибкое и мощное решение. Это реализация интерфейса 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>
Ответ 4
Uri класс реализует ISerializable Интерфейс, чтобы он мог позаботиться о сериализации/десериализации.
Ответ 5
Внедрить и IDeserializationCallback и использовать это поле самостоятельно.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ideserializationcallback.aspx
Ответ 6
Ури уже сериализуется, поэтому я не верю, что вам нужно что-то делать.
http://msdn.microsoft.com/en-us/library/system.uri(VS.80).aspx