How to (xml) serialize a uri

前端 未结 6 2285
南笙
南笙 2020-12-18 20:02

I have a class I\'ve marked as Serializable, with a Uri property. How can I get the Uri to serialize/Deserialize without making the property of type string?

相关标签:
6条回答
  • 2020-12-18 20:28

    For others who found this question and who didn't like the solutions, there is another more flexible and powerful solution. It's implementation IXmlSerializable interface. This more difficult, but it's worth it. You can create any xml that you would like. The simplest example is:

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

    And you get something like this in xml:

    <PriceContainer Code="314" Model="PP500" Name="NuTone PurePower PP500 Power Unit">
        <Image Src="http://www.thinkvacuums.com/images/nutone-pp500-activac.jpg" />
    </PriceContainer>
    
    0 讨论(0)
  • 2020-12-18 20:32

    Uri class implements ISerializable Interface so it should be able to take care of serialization/deserialization.

    0 讨论(0)
  • 2020-12-18 20:35

    With xml serializer, you are limited - it isn't as versatile as (say) some of the binaryformatter/ISerializable options. One frequent trick is to have a second property for serialization:

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

    The two browsable attributes hide it from view (but it needs to be on the public API for XmlSerializer to use it). The XmlIgnore tells it not to try the Uri; and the [XmlAttribute(...)] (or [XmlElement(...)]) tells it to rename UriString when (de)serializing it.

    (note that EditorBrowsable only applies to code outside the assembly declaring the type)

    0 讨论(0)
  • 2020-12-18 20:37

    Based on one of the answers for how to serialize TimeSpan I ended up with this which works quite well for me and doesn't require the additional property:

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

    Then you can use it like this

    public class Settings
    {
         public XmlUri Uri { get; set; }
    }
    
    ...
    var s = new Settings { Uri = new Uri("http://www.example.com") };
    

    And it will nicely serialize and deserialize.

    Note: Can't use the trick with the XmlElement(Type = typeof(...)) attribute as given in another answer in the above linked question as the XmlSerializer checks for an empty default constructor first on the original type.

    0 讨论(0)
  • 2020-12-18 20:41

    Uri is already Serializeable, so I don't belive you have to do anything.

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

    0 讨论(0)
  • 2020-12-18 20:50

    Implement and IDeserializationCallback and use that field on your own.

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

    0 讨论(0)
提交回复
热议问题