2011-04-07 108 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只讀屬性的類是可以接受的。

還是黑客,但這至少是更強大。