如何序列化包含 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
中的那个 属性
如果您愿意根名称是 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.
注意这是.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
如果您愿意根名称是 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.