简体   繁体   English

如何序列化包含 XML 属性的 object

[英]How to serialize an object containing an XML property

Note this is .NET 4.8注意这是 .NET 4.8

I have created this sample code to illustrate the problem我创建了这个示例代码来说明问题

[XmlRoot(ElementName = "RESULT", Namespace = "", IsNullable = false)]
public class Result
{
    public string Message { get; set; }

    public XElement Stuff { get; set; }


    public override string ToString() 
    {
        var ser = new XmlSerializer(GetType());

        using (var stream = new StringWriter())
        {
            ser.Serialize(stream, this);
            return stream.ToString();
        }
    }
}

I will have some XML already that looks like this我会有一些XML看起来像这样

<FOO>
      <BAR>Hello World</BAR>
      <BAR2>Hello World</BAR2>
      <BAR3>Hello World</BAR3>
</FOO>

This is assigned to the XElement Stuff property and when an instance of Result is then serialized, you get this XML:这被分配给XElement Stuff属性,然后当Result的一个实例被序列化时,您会得到这个 XML:

<?xml version="1.0" encoding="utf-16"?>
<RESULT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>Hello World</Message>
  <Stuff>
    <FOO>
      <BAR>Hello World</BAR>
      <BAR2>Hello World</BAR2>
      <BAR3>Hello World</BAR3>
    </FOO>
  </Stuff>
</RESULT>

Question: Is there any way to get this result instead?问题:有没有办法得到这个结果?

<?xml version="1.0" encoding="utf-16"?>
<RESULT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>Hello World</Message>
  <FOO>
    <BAR>Hello World</BAR>
    <BAR2>Hello World</BAR2>
    <BAR3>Hello World</BAR3>
  </FOO>
</RESULT>

Note: FOO could be Stuff - I don't care (because I know how to change that name) I just don't want two levels of nested XML for that property in the serialised XML注意: FOO可能是Stuff - 我不在乎(因为我知道如何更改该名称)我只是不希望序列化 XML 中的该属性有两层嵌套 XML

You can play with the sample code here您可以在此处使用示例代码

If you're happy for the root name to be hard-coded, then you can write a wrapper type for the elements and implement IXmlSerializable within.如果您愿意对根名称进行硬编码,那么您可以为元素编写一个包装器类型并在其中实现IXmlSerializable

This is likely preferable to implementing in Result , as I imagine the real type would have more than 2 properties.这可能比在Result中实现更可取,因为我想真正的类型会有超过 2 个属性。

A quick and dirty example - I'll leave implementing ReadXml to you (if you need it):一个快速而肮脏的例子——我将把ReadXml的实现留给你(如果你需要的话):

public class ElementsWrapper : IXmlSerializable
{   
    public XElement[] Elements { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var element in Elements)
        {
            element.WriteTo(writer);
        }
    }
}

And change your property in Result to:并将您在Result中的属性更改为:

public ElementsWrapper FOO { get; set; }

When used, the serialiser for Result will write <FOO> , then delegate to the custom serialisation, and then write </FOO> .使用时, Result的序列化程序将写入<FOO> ,然后委托给自定义序列化,然后写入</FOO>

You can see an updated fiddle here .您可以在此处看到更新的小提琴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM