如何序列化包含 XML 属性 的对象

How to serialize an object containing an XML property

注意这是.NET 4.8

我创建了这个示例代码来说明问题

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

我已经有一些 XML 看起来像这样

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

这被分配给 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>

问题:有什么方法可以代替这个结果吗?

<?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>

注意:FOO 可能是 Stuff - 我不在乎(因为我知道如何更改该名称)我只是不想要两层嵌套XML 对于序列化 XML

中的那个 属性

You can play with the sample code here

如果您愿意根名称是 hard-coded,那么您可以为元素编写一个包装器类型并在其中实现 IXmlSerializable

这可能比在 Result 中实现更可取,因为我想真正的类型会有 2 个以上的属性。

一个简单粗暴的例子 - 我会把实现 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);
        }
    }
}

并将 Result 中的 属性 更改为:

public ElementsWrapper FOO { get; set; }

使用时,Result 的序列化程序将写入 <FOO>,然后委托给自定义序列化,然后写入 </FOO>

您可以看到更新后的 fiddle here.