深度xml序列化结构选项

时间:2009-01-15 07:19:30

标签: c# xml-serialization

我有下面显示的类和结构。如果我将类序列化为 我正在使用xmlserializer:

<试验>
  < TestNumber1> 5< / TestNumber1>
  < InnerTest />
< /测试>

什么是使InnerTest正确序列化的最简单方法 (最好使用xmlserializer)而不给出Number属性a 设定装置?

谢谢, 尼克

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; }} 
} 

4 个答案:

答案 0 :(得分:2)

正如Jon Skeet所说的那样,如果您不想为属性设置公共获取/设置,则需要将IXmlSerializableXmlSerializer一起使用,因为它可以在部分信任环境因此无法访问您无法访问的任何数据(回答他的最后一部分 - 是的,像DateTime这样的结构确实在该序列化程序中有明确的支持。)

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

(我一直在讨论两者兼而有之的问题,即XmlSerializer的灵活性与DataContractSerializer等私人成员序列化的能力,但遗憾的是目前还没有人。)

答案 1 :(得分:2)

如果可能在这种情况下,我会使用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版本,该版本在整个过程中使用可变类,并在两者之间进行转换;再次,作为大型物体模型的选择不是很有吸引力。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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

Test test = new Test { TestNumber1 = 5 };

XmlSerializer xmlSer = new XmlSerializer(typeof(Test));
MemoryStream memStm = new MemoryStream();

xmlSer.Serialize(memStm, test);

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

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

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

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

享受!