C# 如何 (xml) 序列化 uri

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1036492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:39:24  来源:igfitidea点击:

How to (xml) serialize a uri

c#.netxml-serialization

提问by Jeremy

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?

我有一个标记为 Serializable 的类,带有一个 Uri 属性。如何在不创建字符串类型属性的情况下让 Uri 进行序列化/反序列化?

采纳答案by ChrisWue

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

基于如何序列化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());
    }
}

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 XmlSerializerchecks for an empty default constructor first on the original type.

注意:不能使用XmlElement(Type = typeof(...))上面链接问题中另一个答案中给出的属性的技巧,因为XmlSerializer首先在原始类型上检查空的默认构造函数。

回答by TheVillageIdiot

Uriclass implements ISerializableInterface so it should be able to take care of serialization/deserialization.

Uri类实现了ISerializable接口,因此它应该能够处理序列化/反序列化。

回答by Kobi

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

Uri 已经是可序列化的,所以我不相信你必须做任何事情。

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

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

回答by Timotei

Implement and IDeserializationCallback and use that field on your own.

实现和 IDeserializationCallback 并自行使用该字段。

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

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

回答by Marc Gravell

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

使用 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);}
}

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

两个可浏览的属性将其隐藏起来(但它需要在公共 API 上XmlSerializer才能使用)。该XmlIgnore告诉它不要尝试Uri; 并且[XmlAttribute(...)](或[XmlElement(...)])告诉它UriString在(反)序列化它时重命名。

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

(请注意,EditorBrowsable仅适用于声明类型的程序集之外的代码)

回答by Pixel

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:

对于发现此问题但不喜欢解决方案的其他人,还有另一种更灵活、更强大的解决方案。它实现了 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();
        }
    }
}

And you get something like this in xml:

你会在 xml 中得到这样的东西:

<PriceContainer Code="314" Model="PP500" Name="NuTone PurePower PP500 Power Unit">
    <Image Src="http://www.thinkvacuums.com/images/nutone-pp500-activac.jpg" />
</PriceContainer>