3

我有這樣一類:二進制序列和自動屬性

public class Foo 
{ 
    public IBar {get;set;} 
    //tons of other properties 
} 

public interface IBar 
{ 
    //whatever 
} 

類用於二進制序列化(標準使用的BinaryFormatter的)。 IBar的實現以[Serializable]標記,因此一切正常。

現在我想不要序列化欄和保留向後兼容性(它沒有在代碼中引用)。 NonSerialized屬性似乎夠用了。但是,它只能應用於字段,而不能應用於自動屬性。所以我試過這個:

public class Foo 
{ 
    private IBar _bar; 
    [NonSerializable] 
    public IBar Bar 
    { 
     get { return _bar; } 
     set { _bar = value; } 
    } 
} 

令人驚訝的是,它運行良好 - 我可以反序列化舊的Foos和新的。

我的問題是:如果這些字段是序列化的字段,並且自動屬性的後臺字段可能在其名稱中包含一些非C#字符,它怎麼可能工作?

換句話說:

老Foo的伊巴爾字段名(我猜測):k__BackingField

新富的伊巴爾字段名稱:_bar

顯然它們不匹配,所以如何BinaryFormatter的克服了這一?

+0

當你說該屬性從未在代碼中引用並不意味着它總是'null'?如果是這樣的話,爲什麼它可以反序列化整個二進制不兼容性的答案是,它實際上從來不需要。 – JRoughan 2013-02-28 11:06:15

+0

我不夠精確。該屬性在構造函數中被分配了一個值。它從未在其他地方引用過。坦率地說,它應該從Foo中刪除。 – dzendras 2013-02-28 12:08:01

+0

您的「舊」代碼在語法上是錯誤的 - 請指定屬性名稱,因爲它幾乎肯定會影響行爲。 – 2017-05-31 15:23:54

回答

1

我覺得在你的例子中有一些奇怪的東西。 BinaryFormatter不應該能夠處理這個問題(據我所知,除非在4.5中有所改變,我懷疑它),這就是爲什麼如果需要向後兼容是非常危險的。您確定該值是從舊版本序列化並反序列化爲新版本?你可以驗證反序列化的數據是否匹配,而不是null?

有關驗證程序的完整示例而不是的工作,請參見此處。 http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx

您不會看到任何異常,但名稱爲xyz__backingfield的字段中的舊值將丟失,並在新類中被替換爲默認值。

如果您想要向後兼容,請避免使用自動屬性,否則您很快就會陷入麻煩的世界。事實上,這並不重要,因爲如果您想在同一個應用程序中序列化對象並將其反序列化,例如對於複製&粘貼或類似操作,BinaryFormatter在默認(自動)模式下才非常有用。在這種情況下,你不會有任何版本問題,因爲它將是同時執行序列化和反序列化的代碼。

要使序列化向後兼容而不會失去主意,請確保完全控制架構。 DataContractSerializer,Json.NET或協議緩衝區(例如protobuf-net)可以很好地避免麻煩。

作爲最後的可能性,您可以實現ISerializable並使用BinaryFormatter的字典存儲,但是您仍然有手動滾動序列化的所有缺點。

在旁註中,如果您想將屬性應用於支持字段try [field:AttriuteType],這對於將事件的支持字段標記爲非序列化非常有用。

+0

謝謝你的迴應。不幸的是切換到任何其他序列化器已經太晚了。我必須使用BinaryFormatter來制定解決方法,並且有時間(將來)完全擺脫BinarySerialization。 – dzendras 2013-02-28 13:10:34