2011-04-07 30 views
29

在C#中,我有一个具有应该通过XML序列化的派生属性的类。但是,XML序列化(默认情况下)不会序列化只读属性。我可以解决此通过定义一个空的二传手,像这样:强制XML序列化以序列化只读属性

public virtual string IdString 
{ 
    get { return Id.ToString("000000"); } 
    set { /* required for xml serialization */ } 
} 

但有一个更清洁更语义正确的方式,总之我自己写的ISerializable实现的?

+0

如果我正确理解这一点,你有一个IdString被序列化到XML文件,但当类被反序列化时被忽略? – 2011-04-07 17:57:20

+0

IdString将始终从Id属性派生,该属性获得序列化和反序列化。 – Chris 2011-04-07 18:22:09

+10

在这种情况下,你为什么要串行化IdString? – Justin 2011-04-08 07:51:38

回答

13

总之,没有。使用XmlSerializer可以实现IXmlSerializable(这是非平凡的),或者编写一个基本的DTO(完全读写),然后从DTO模型转换到您的主模型。

请注意,在某些情况下,DataContractSerializer是一个可行的选项,但它不提供对XML的相同控制。然而,与DCS你可以这样做:

[DataMember] 
public int Id { get; private set; } 
+3

'IXmlSerializable'实际上对这个问题非常有效,特别是如果你只是序列化而不是反序列化,并且这并不难。看看这个:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly – cjbarth 2013-01-25 19:55:55

18

老实说,这似乎并没有太对我不好,只要它是记录

你或许应该抛出一个异常,如果设置器实际上是调用:

/// <summary> 
/// Blah blah blah. 
/// </summary> 
/// <exception cref="NotSupportedException">Any use of the setter for this property.</exception> 
/// <remarks> 
/// This property is read only and should not be set. 
/// The setter is provided for XML serialisation. 
/// </remarks> 
public virtual string IdString 
{ 
    get 
    { 
     return Id.ToString("000000"); 
    } 
    set 
    { 
     throw new NotSupportedException("Setting the IdString property is not supported"); 
    } 
} 
+8

这不会导致反序列化失败,只是因为这个异常然后被抛出? – primfaktor 2011-07-22 07:53:09

+2

@primfaktor是的,但正如我所理解的问题是重点(它永远不会被反序列化)。如果这不是你想要的行为,你可以在setter中不做任何事情,甚至解析字符串并设置'Id'属性(可能只有在它尚未设置的情况下)。 – Justin 2011-07-22 08:35:08

+1

哦,当然。写这篇文章时,我对咖啡因的适应性很低。 – primfaktor 2011-07-25 11:25:08

1

要取溶液远一点,让反序列化的工作,以及...

public class A 
{ 
    private int _id = -1; 

    public int Id 
    { 
     get { return _id; } 
     set 
     { 
      if (_id < 0) 
       throw new InvalidOperationException("..."); 

      if (value < 0) 
       throw new ArgumentException("..."); 

      _id = value; 
     } 
    } 
} 

这将允许Id刚好一次设置为大于或等于0的值。任何试图设置它的尝试都将导致InvalidOperationException。这意味着在反序列化期间XmlSerializer将能够设置Id,但它将永远无法在之后进行更改。请注意,如果该属性是一个引用类型,那么你可以检查null。

如果您有很多只读属性来序列化/反序列化,这可能不是最好的解决方案,因为它需要大量的样板代码。但是,我发现这对于具有1-2只读属性的类是可以接受的。

还是黑客,但这至少是更强大。