【问题标题】:Using IXmlSerializable interface on complex object graph在复杂对象图上使用 IXmlSerializable 接口
【发布时间】:2011-03-11 04:07:30
【问题描述】:

如果使用自定义 XML 序列化 (IXmlSerialiable),在包含具有组成复杂对象的属性的复杂对象上使用自定义IXmlSerializable 接口,如何您是否在 IXmlSerializable.ReadXml(XmlReader reader) 方法中指定您希望反序列化程序对这些子属性使用普通反序列化?

注意:类似于this question

【问题讨论】:

    标签: .net xml ixmlserializable xml-serialization


    【解决方案1】:

    IXmlSerializable 实现起来有点乏味,因为它几乎是一种全有或全无的方法,因为您无法为正常的 XML 序列化选择子类型。但是,如果我对您的理解正确,您可以通过为未实现 IXmlSerializable 的类型手动创建 XmlSerializer 来实现您想要的。

    例如,如果我们从两个类开始,Default 不实现 IXmlSerializableCustom 实现它。

    public class Default // Uses default XML Serialization
    {
        public int Count { get; set; }
    }
    
    public class Custom : IXmlSerializable
    {
        public int Count { get; set; }
    
        public XmlSchema GetSchema() { throw new NotImplementedException(); }
    
        public void ReadXml(XmlReader reader)
        {
            reader.ReadToDescendant("Count");
            this.Count = reader.ReadElementContentAsInt();
        }
    
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Custom");
            writer.WriteElementString("Count", this.Count.ToString());
            writer.WriteEndElement();
        }
    }
    

    然后我们创建第三个类Parent,它具有前面每个实例的子类,并以一种为支持它的子类调用ReadXml/WriteXml 方法并为另一个实例创建默认XML 序列化程序的方式实现IXmlSerializable孩子。

    public class Parent : IXmlSerializable
    {
        public Parent()
        {
            this.Default = new Default { Count = 1 };
            this.Custom = new Custom { Count = 2 };
        }
    
        public Default Default { get; set; }
        public Custom Custom { get; set; }
    
        public XmlSchema GetSchema() { throw new NotImplementedException(); }
    
        public void ReadXml(XmlReader reader)
        {
            reader.ReadToFollowing("Custom");
            this.Custom = new Custom();
            this.Custom.ReadXml(reader);
    
            reader.ReadToFollowing("Default");
            var serializer = new XmlSerializer(typeof(Default));
            this.Default = (Default)serializer.Deserialize(reader);
        }
    
        public void WriteXml(XmlWriter writer)
        {
            this.Custom.WriteXml(writer);
    
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            new XmlSerializer(typeof(Default)).Serialize(writer, this.Default, ns);
        }
    }
    

    为了使示例完整,一个对Parent 实例进行序列化和反序列化的示例程序:

    static void Main()
    {
        var sb = new StringBuilder();
        var serializer = new XmlSerializer(typeof(Parent));
    
        serializer.Serialize(new StringWriter(sb), new Parent());
    
        Console.WriteLine(sb);
    
        var parent = (Parent)serializer.Deserialize(new StringReader(sb.ToString()));
    
        Console.WriteLine("Parent.Custom.Count: {0}", parent.Custom.Count);
        Console.WriteLine("Parent.Default.Count: {0}", parent.Default.Count);
    }
    

    【讨论】:

    • 谢谢这么多...我正要尝试这个..但表面上看起来正是我所需要的..
    • 一点注意:您可以在 WriteXml()/ReadXml() 方法中对 Default 和 Custom 对象使用 XmlSerializer。
    • 当您反序列化一个子对象并将其传递给XmlReader 时,读取器指针是否最终位于正确的位置(就在子元素的末尾),还是延迟了?
    猜你喜欢
    • 2015-02-10
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    相关资源
    最近更新 更多