使用.NET XML序列化在其他元素中包装序列化属性
我使用C#+ VSTS2008 + .Net 3.0来进行XML序列化。 代码工作正常。 下面是我的代码和当前序列化的XML结果。
现在我想在输出XML文件中添加两个附加层。 这是我期望的XML结果。 有什么简单的方法吗? 我不确定NestingLevel是否可以帮助这样做。 我想找到一种不会改变MyClass和MyObject结构的简单方法。
预期的XML序列化结果,
Foo
当前的XML序列化结果,
Foo
我目前的代码,
public class MyClass { public MyObject MyObjectProperty; } public class MyObject { public string ObjectName; } public class Program { static void Main(string[] args) { XmlSerializer s = new XmlSerializer(typeof(MyClass)); FileStream fs = new FileStream("foo.xml", FileMode.Create); MyClass instance = new MyClass(); instance.MyObjectProperty = new MyObject(); instance.MyObjectProperty.ObjectName = "Foo"; s.Serialize(fs, instance); return; } }
我想找到一种不会改变MyClass和MyObject结构的简单方法。
坦率地说,这不会发生。 XmlSerializer
(简单地使用时)遵循类/成员的结构。 因此,您无法在不更改结构的情况下添加额外的图层。
当以定制的方式使用( IXmlSerializable
)时,您可以肯定的一点是它并不简单……这不是一个有趣的界面来实现。
我的建议:介绍一个模仿你想要的格式的DTO,并在序列化之前填充它。
为什么还需要这两个额外的图层?
是业务需求,您应该将这两个对象添加到对象模型中:
public class MyClass { public AdditionalLayer1 AdditionalLayer1; } public class AdditionalLayer1 { public AdditionalLayer2 AdditionalLayer2; } public class AdditionalLayer2 { public MyObject MyObjectProperty; } public class MyObject { public string ObjectName; }
如果纯粹是因为某些兼容性要求,你可以做上面的事情,或者在MyClass上实现IXmlSerializable:
public class MyClass : IXmlSerializable { public MyObject MyObjectProperty; public void WriteXml (XmlWriter writer) { //open the two layers //serialize MyObject //close the two layers } public void ReadXml (XmlReader reader) { //read all the layers back, etc } public XmlSchema GetSchema() { return(null); } }
您可以在序列化后使用XSL进行转换并添加“缺失”标记。
我建议序列化到MemoryStream
而不是FileStream
,然后将XML加载到XmlDocument
,然后使用该类的方法插入所需的额外节点。 之后,您可以将其保存。
我最近才这样做,并没有发现在所有困难或复杂的情况下重写IXmlSerializable接口。 序列化/反序列化正常但对于包含子类的类,您需要在IXmlSerializable派生的额外标记中包含该子类:
class ContainingClass : IXmlSerializable { ... #region IXmlSerializable Members public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { **reader.ReadStartElement("Equipment");** XmlSerializer ser = new XmlSerializer(typeof(Host)); while (reader.NodeType != XmlNodeType.EndElement) { Host newHost = new Host(); newHost.Name = (string) ser.Deserialize(reader); _hosts.Add(newHost); reader.Read(); } // Read the node to its end. // Next call of the reader methods will crash if not called. **reader.ReadEndElement(); // "Equipment"** } public void WriteXml(XmlWriter writer) { XmlSerializer ser = new XmlSerializer(typeof(Host)); **writer.WriteStartElement("Equipment");** foreach (Host host in this._hosts) { ser.Serialize(writer, host); } **writer.WriteEndElement();** } #endregion
我在这里所做的就是包装低级对象的de / serialization。 在这里,我在这个类的集合中的所有主机周围包装了一个额外的标签“Equipment”。 您可以在此处添加任意数量的标签,只要您关闭每个标签即可。
注意:Bold显示为**文本** – 只是确保你摆脱双星号:)