5

我有如下所示的类和结构。如果我像使用 xmlserializer 一样序列化类,我会得到:

<Test>
<TestNumber1>5</TestNumber1>
<InnerTest/>
</Test>

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

谢谢,尼克

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

4 回答 4

2

正如 Jon Skeet 所说的那样,如果您不想对属性进行公共获取/设置,则需要IXmlSerializableXmlSerializer无论如何您都无法访问(回答他的最后一部分-是的,某些结构DateTime确实在该序列化程序中具有明确的支持)。

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

(长期以来,我一直渴望将两者结合起来的东西,即XmlSerializer具有序列化私人成员的能力的灵活性,DataContractSerializer但不幸的是,目前还没有。)

于 2009-01-15T07:40:08.923 回答
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)]- 来装饰它,但这并不理想)。

当然,如果你在结构上有多个值......更棘手。当然,您可以拥有多个 shim 属性,但这有点杂乱无章。基本上,[反]序列化和不可变对象(作为结构应该是)并不能很好地混合。

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

于 2009-01-15T08:01:50.627 回答
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] 以及更多可以根据需要进行调整的属性。

享受!

于 2009-01-15T17:12:40.750 回答
1

我自己从来没有做过,但我怀疑你只需要实现IXmlSerializable接口。

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

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

于 2009-01-15T07:29:31.580 回答