在复杂对象图上使用 IXmlSerialized 接口

发布于 2024-09-08 04:17:51 字数 349 浏览 11 评论 0原文

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

注意:类似于这个问题

If using custom XML Serialization (IXmlSerialiable), on a complex object that contains properties with constituent complex objects which do NOT use custom IXmlSerializable interface, how do you specify, in the IXmlSerializable.ReadXml(XmlReader reader) method, that you want the deserializer to use the ordinary deserialization on those child properties?

NOTE: similar to this question

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨落星ぅ辰 2024-09-15 04:17:51

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

例如,如果我们从两个类开始,Default 没有实现 IXmlSerialized ,而 Custom 则实现了它。

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 方法的方式实现 IXmlSerialized为支持它的子级并为另一个子级创建默认的 XML 序列化器。

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

The IXmlSerializable is a bit tedious to implement since it's pretty much an all or nothing approach given that you cannot select child types for normal XML serialization. However, if I understood you correctly you can achieve what you want by manually creating XmlSerializer for the types that do not implement IXmlSerializable.

For example, if we start with two classes, Default that does not implement IXmlSerializable and Custom which does implement it.

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

Then we create a third class Parent that has a child of each of the previous instances and implements IXmlSerializable in a way that calls ReadXml/WriteXml methods for the child that supports it and create default XML serializer for the other child.

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

To make the example complete, a sample program that serializes and deserializes a Parent instance:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文