实现 IXmlSerializable 的正确方法? [英] Proper way to implement IXmlSerializable?

查看:39
本文介绍了实现 IXmlSerializable 的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一旦程序员决定实现IXmlSerializable,实现它的规则和最佳实践是什么?我听说 GetSchema() 应该返回 null 并且 ReadXml 应该在返回之前移动到下一个元素.这是真的?那么 WriteXml 怎么样——它应该为对象写一个根元素还是假设已经写了根元素?应该如何处理和编写子对象?

Once a programmer decides to implement IXmlSerializable, what are the rules and best practices for implementing it? I've heard that GetSchema() should return null and ReadXml should move to the next element before returning. Is this true? And what about WriteXml - should it write a root element for the object or is it assumed that the root is already written? How should child objects be treated and written?

这是我现在拥有的示例.我会在收到好的回复后更新它.

Here's a sample of what I have now. I'll update it as I get good responses.

public class MyCalendar : IXmlSerializable
{
    private string _name;
    private bool _enabled;
    private Color _color;
    private List<MyEvent> _events = new List<MyEvent>();


    public XmlSchema GetSchema() { return null; }

    public void ReadXml(XmlReader reader)
    {
        if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyCalendar")
        {
            _name    = reader["Name"];
            _enabled = Boolean.Parse(reader["Enabled"]);
            _color   = Color.FromArgb(Int32.Parse(reader["Color"]));

            if (reader.ReadToDescendant("MyEvent"))
            {
                while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyEvent")
                {
                    MyEvent evt = new MyEvent();
                    evt.ReadXml(reader);
                    _events.Add(evt);
                }
            }
            reader.Read();
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString("Name",    _name);
        writer.WriteAttributeString("Enabled", _enabled.ToString());
        writer.WriteAttributeString("Color",   _color.ToArgb().ToString());

        foreach (MyEvent evt in _events)
        {
            writer.WriteStartElement("MyEvent");
            evt.WriteXml(writer);
            writer.WriteEndElement();
        }
    }
}

public class MyEvent : IXmlSerializable
{
    private string _title;
    private DateTime _start;
    private DateTime _stop;


    public XmlSchema GetSchema() { return null; }

    public void ReadXml(XmlReader reader)
    {
        if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyEvent")
        {
            _title = reader["Title"];
            _start = DateTime.FromBinary(Int64.Parse(reader["Start"]));
            _stop  = DateTime.FromBinary(Int64.Parse(reader["Stop"]));
            reader.Read();
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString("Title", _title);
        writer.WriteAttributeString("Start", _start.ToBinary().ToString());
        writer.WriteAttributeString("Stop",  _stop.ToBinary().ToString());
    }
}

对应的示例 XML

<MyCalendar Name="Master Plan" Enabled="True" Color="-14069085">
    <MyEvent Title="Write Code" Start="-8589241828854775808" Stop="-8589241756854775808" />
    <MyEvent Title="???" Start="-8589241828854775808" Stop="-8589241756854775808" />
    <MyEvent Title="Profit!" Start="-8589247048854775808" Stop="-8589246976854775808" />
</MyCalendar>

推荐答案

Yes, GetSchema() 应该返回 null.

Yes, GetSchema() should return null.

IXmlSerializable.GetSchema 方法 这个方法是保留的,不应该是用过的.实施时IXmlSerializable 接口,你应该返回一个空引用(没有在Visual Basic)从这个方法,而是,如果指定自定义架构是需要,应用XmlSchemaProviderAttribute 到班级.

IXmlSerializable.GetSchema Method This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return a null reference (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the XmlSchemaProviderAttribute to the class.

无论是读还是写,对象元素都已经写好了,所以不需要在写的时候再添加外层元素.比如你可以直接开始读/写两者中的属性.

For both read and write, the object element has already been written, so you don't need to add an outer element in write. For example, you can just start reading/writing attributes in the two.

对于写入:

WriteXml 实现你提供应该写出XML对象的表示.这框架编写一个包装元素和将 XML 编写器定位在其之后开始.你的实现可能会写其内容,包括子元素.然后框架关闭包装元素.

The WriteXml implementation you provide should write out the XML representation of the object. The framework writes a wrapper element and positions the XML writer after its start. Your implementation may write its contents, including child elements. The framework then closes the wrapper element.

对于阅读:

ReadXml 方法必须重构您的对象使用的信息由 WriteXml 方法编写.

The ReadXml method must reconstitute your object using the information that was written by the WriteXml method.

当这个方法被调用时,reader位于开头包装信息的元素你的类型.也就是说,就在指示开始的开始标记一个序列化的对象.当这方法返回,它必须读取从头到尾的整个元素,包括其所有内容.不像WriteXml 方法,框架不处理包装元素自动地.您的实施必须这样做.不遵守这些定位规则可能会导致代码生成意外的运行时异常或损坏的数据.

When this method is called, the reader is positioned at the start of the element that wraps the information for your type. That is, just before the start tag that indicates the beginning of a serialized object. When this method returns, it must have read the entire element from beginning to end, including all of its contents. Unlike the WriteXml method, the framework does not handle the wrapper element automatically. Your implementation must do so. Failing to observe these positioning rules may cause code to generate unexpected runtime exceptions or corrupt data.

我同意这有点不清楚,但归结为你的工作是Read()包装器的结束元素标签".

I'll agree that is a little unclear, but it boils down to "it is your job to Read() the end-element tag of the wrapper".

这篇关于实现 IXmlSerializable 的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆