2013-02-19 32 views
5

給出一點背景。將數據保存到.net中的文件時的良好編碼實踐

我創建了一個應用程序,允許用戶保存設置,然後在稍後的日期調用設置。爲此,我創建了一些可序列化的對象。我已經得到這個使用BinaryFormatter工作沒有太大麻煩。

我開始遇到問題的時候是我升級軟件並添加新設置。現在我的可序列化的對象不匹配,所以我必須更新文件。我已經成功完成了幾個版本。但要做到這一點,我嘗試反序列化文件,如果它引發異常,我嘗試下一個版本。 。然後是下一個。 。然後是下一個。 。 。直到我找到合適的人。然後,我必須爲每個舊版本編寫轉換函數,以將其轉換爲最新版本。我也創建了一個「修訂」文件,所以我可以檢查他們的版本,然後升級它,但我仍然需要保留許多不同的「版本」,併爲它們編寫轉換函數。 。 。這對我來說本質上是混亂的,如果我繼續沿着這條路線走下去,那麼容易在後面臃腫。

必須有更好的方法來做到這一點,我只是不知道如何。

感謝

+0

在.net框架中內置了功能,從版本2開始,它完全符合您的需求,而無需編寫自己的代碼。請參閱下面的答案。 – Andy 2013-02-19 22:57:03

回答

3

你需要寫一個serialization binder解決組件。

對於設置,我使用Dictionary<string, byte[]>保存到文件。我序列化字典,一切都很好。當我添加新的設置時,如果在設置文件中找不到,我會提供默認設置。

另外,如果您將字段添加到序列化對象,則可以使用[可選]進行修飾。

0

實際上,這可以通過將[DefaultValue()]屬性添加到設置對象上的較新屬性來完成 - 至少對於XML序列化來說。我沒有嘗試過使用二進制序列化。對於xml,這意味着它們是「可選的」,並且在加載舊版本的文件時序列化不會中斷。您可以在名稱空間System.ComponentModel中找到此屬性;

class MySettings 
{ 
    public int MaxNumLogins { get; set; } 

    // specify the value to default to if it's not present in the serialized file... 
    [DefaultValue(0)] 
    public int CacheTimeoutMinutes { get; set; } 
} 
+0

二進制序列化比XML序列化更挑剔,我認爲它不會起作用。 – 2013-02-19 22:46:18

0

除了將字段命名爲其他人所建議的這種類型的東西,只是爲了版本號而大聲呼喊。

2

這正是Settings類的用途。您可以在app.config中定義默認值,然後用戶可以更改它們,當您保存時,它們的更改將保存到其用戶配置文件中的某個位置。當你閱讀它們時,你會得到修改的設置。

這個鏈接是VS 2005,但它的工作原理完全在VS 2012是相同的:http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx

找到的鏈接,VS2012:http://msdn.microsoft.com/EN-US/library/k4s6c3a0(v=VS.110,d=hv.2).aspx

+0

很高興知道,謝謝。這不是我所需要的,但我將來可能會使用它。 – EatATaco 2013-02-21 16:08:29

+0

@EatATaco在你的問題中沒有任何東西讓我覺得你正在做一些內置功能沒有提供的東西,所以它看起來像你正在重新發明輪子。也許你可以更新你的問題,所以我們可以知道爲什麼內置設置不適合這個。 – Andy 2013-02-21 20:57:59

0

你可以看看protobuf網http://code.google.com/p/protobuf-net/wiki/GettingStarted如果你是做二進制,因爲所有這些東西都涵蓋了版本控制等。它也非常緊湊。它也是積極開發的,如果你使用.proto文件,如果你有潛在的跨平臺需求,你也可以實現。

如果您希望人們能夠編輯設置(在您的程序之外),那麼您可以使用XML *序列化方法。

1

XML格式適用於這種情況。您會在設置文件的早期版本中找到必要的舊設置。甚至舊版本也可以處理從較新版本創建的XML設置。它不能「自動」工作,即使用像Serialize/Deserialize這樣的方法,但編寫轉換函數並不容易或更快。