Вопрос по c#, .net – Как (XML) сериализовать URI

16

У меня есть класс, помеченный как Serializable, со свойством Uri. Как я могу получить Uri для сериализации / десериализации без использования свойства типа string?

Теги предлагают XmlSerializer; на самом деле вам не нужен [Serializable] для этого - тип просто должен быть публичным. Marc Gravell♦

Ваш Ответ

6   ответов
-1

Uri уже доступен для сериализации, поэтому я не верю, что вам нужно что-то делать.

http://msdn.microsoft.com/en-us/library/system.uri(VS.80).aspx

Error: User Rate Limit Exceeded
0

Uri реализует классISerializable Интерфейс, поэтому он должен быть в состоянии позаботиться о сериализации / десериализации.

Error: User Rate Limit Exceeded Jeremy
Error: User Rate Limit ExceededbinaryError: User Rate Limit ExceededxmlError: User Rate Limit Exceeded
32

С сериализатором xml вы ограничены - он не настолько универсален, как (скажем) некоторые из двоичных форматеров /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 когда (де) сериализует его.

(Обратите внимание, чтоEditorBrowsable применяется только к коду вне сборки, объявляющему тип)

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
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>
12

На основании одного из ответов длякак сериализовать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 сначала проверяет пустой конструктор по умолчанию для исходного типа.

0

Внедрите и IDeserializationCallback и используйте это поле по своему усмотрению.

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ideserializationcallback.aspx

Error: User Rate Limit Exceeded

Похожие вопросы