深度xml序列化结构选项

我有下面显示的类和结构。 如果我使用xmlserializer序列化类,我得到:

5

什么是最简单的方法使InnerTest序列化正确(最好使用xmlserializer)而不给Number属性一个setter?

谢谢,尼克

public class Test { private InnerTest innerTest; private int testNumber; public Test() { this.innerTest = new InnerTest(); this.testNumber = 5; } public int TestNumber1 { get { return this.testNumber; } set { this.testNumber = value;} } public InnerTest InnerTest { get { return this.innerTest; } set { this.innerTest = value;} } } public struct InnerTest { private int number; public InnerTest(int number) { this.number = number; } public int Number{get { return number; }} } 

正如Jon Skeet非常正确地说,如果您不希望为属性设置公共get / set,则需要将IXmlSerializableXmlSerializer一起使用,因为它设计为在部分信任环境中工作,因此不会访问任何无论如何你都无法访问的数据(回答他的最后一部分 – 是的,像DateTime这样的结构确实在该序列化程序中有明确的支持)。

根据您要实现的目标以及您正在使用的.NET版本,您可以考虑使用不需要公开的DataContractSerializer (例如,您可以将DataMemberAttribute放在私有字段上,或者公共吸气者和私人安装者的财产)。 这个序列化程序可以减少对XML格式的控制(实际上它是非常严格的 – 例如它甚至不支持属性!)但是回报更快一些。

(我一直在讨论两者的结合,即XmlSerializer的灵活性与序列化私有成员的能力,如DataContractSerializer但不幸的是目前还没有。)

如果可能在这种情况下,我会使用DataContractSerializer (.NET 3.0),我会使用类似的东西:

 [DataMember] public int TestNumber1 { get { return this.testNumber; } set { this.testNumber = value;} } // note **not** a data-member public InnerTest InnerTest { get { return this.innerTest; } set { this.innerTest = value;} } [DataMember] private int InnerTestValue { get {return innerTest.Number;} set {innerTest = new InnerTest(value);} } 

从而踩到了这个问题。 你可以用XmlSerializer做类似的事情,但是你需要公开InnerTestValue (尽管你可以用[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]来装饰它 – 但这并不理想。

当然,如果你在struct上有多个值…更棘手。 当然,你可以有多个垫片属性,但这有点斗志。 基本上,[de]序列化和不可变对象(应该是结构)不能很好地混合。

另一个选择是维护一个单独的POCO版本,它在整个过程中使用可变类,并在两者之间进行转换; 再次,作为大型对象模型的选项不是很有吸引力。

我自己从未这样做过,但我怀疑你只需要实现IXmlSerializable接口。

据我所知,这意味着你必须让你的结构变得可变 – 这是一种痛苦。 理想情况下,XmlSerializer应该识别你的类型是否有一个具有特定签名的构造函数,但因为这似乎不是一个选项(据我所知),使用显式接口实现至少不鼓励实现接口是值得的用户直接自己使用它。

我想知道其他结构(例如DateTime)如何管理…也许他们在XmlSerializer中有明确的支持。

你绝对可以在你的对象上使用XmlSerializer并获得预期的结果:

 Test test = new Test { TestNumber1 = 5 }; XmlSerializer xmlSer = new XmlSerializer(typeof(Test)); MemoryStream memStm = new MemoryStream(); xmlSer.Serialize(memStm, test); 

要validation结果,请再次将内存流读出为字符串并在调试器中查看(或将其写入文件):

 StreamReader stmR = new StreamReader(memStm); memStm.Position = 0; string output = stmR.ReadToEnd(); 

如果您没有做任何特殊操作,那么您要序列化的类的所有公共属性将在生成的XML中呈现为XML元素…..

有许多属性,如[XmlIgnore],还有更多根据需要进行调整。

请享用!