0

我提交了WP7應用程序的更新,並且我有用戶抱怨他們的數據在更新後被擦除。我通過將我的ViewModel類作爲XML文件序列化到IsolatedStorage中來存儲我的數據。在我的測試過程中,我注意到更新應用程序導致設置文件被我的ViewModel對象的新實例的序列化副本(具有默認值)部分覆蓋。當我寫入我的XML文件時,我認爲我已經通過使用FileMode.Create解決了這個問題,但我想不是。WP7 IsolatedStorage XML文件在應用程序更新後爲空

序列化是否會出錯,因爲我向ViewModel對象添加了新屬性,並且從現有XML文件反序列化失敗?如果不能從XML文件讀取,我確實有我的代碼集來實例化新的ViewModel對象。如果是這種情況,是否意味着我無法向ViewModel對象添加任何新屬性?

編輯:
這裏是我的視圖模型的結構,而不是真的那麼複雜:

public class MyClass: INotifyPropertyChanged 
{ 
    public MyClass() 
    { 
     // Set defaults 
     this.Items= new ObservableCollection<Item>(); 
     this.TextTemplate = "default"; 
     this.HasSeenSomething = false; 
    } 

    public ObservableCollection<Item> Items { get; set; } 
    // New properties added in app update 
    public string TextTemplate { get; set; } 
    public bool HasSeenSomething { get; set; } 
} 

這裏是我使用的序列化/反序列化我的視圖模型的代碼。我認爲這是非常標準的,但也許我已經拙劣的東西:

public static void WriteToXml<T>(T data, string path) 
{ 
    var xmlWriterSettings = new XmlWriterSettings { Indent = true }; 
    using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication()) 
    { 
     using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Create)) 
     { 
      var serializer = new XmlSerializer(typeof(T)); 
      using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings)) 
      { 
       serializer.Serialize(xmlWriter, data); 
      } 
     } 
    } 
} 

public static T ReadFromXml<T>(string path) 
{ 
    T data = default(T); 
    try 
    { 
     using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication()) 
     { 
      if (myIsolatedStorage.FileExists(path)) 
      { 
       using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Open)) 
       { 
        try 
        { 
         var serializer = new XmlSerializer(typeof(T)); 
         object instance = serializer.Deserialize(stream); 
         if (instance != null) data = (T)instance; 
        } 
        catch (System.Exception ex) 
        { 
         var e = ex; 
        } 
       } 
      } 
     } 
    } 
    catch(System.Exception ex) 
    { 
     var e = ex; 
    } 
    return data; 
} 

回答

0

你可以,但有幾個陷阱。

  1. 你需要確保你沒有改變它們反序列化時會破壞的屬性。所以將Int更改爲String是可以的(雖然我不會建議),但相反可能會中斷。
  2. 您需要記住,當您反序列化對象時,ctor不會被調用。這意味着,如果你這樣做,在構造函數中,以下幾點:

    公共MyClass的(){ MyV2Collection =新集(); }

而且你有沒有其他的機制,新的,如果它是空集,你會在NullRef你第一次嘗試訪問屬性死亡。

一毛錢美元,我敢打賭,你正在打#2。

修復它是相當容易的,但你需要記住去做。選項如下:

  1. 在屬性訪問器中,檢查支持字段是否爲空並且如果它是實例化的。
  2. 創建一個具有[OnDeserialized]屬性裝飾它的函數(public)。該代碼將在反序列化完成時運行,並且您可以在那裏實例化您的成員。
+0

我不認爲空收集是問題。該集合中會有數據,否則用戶不會有任何東西丟失。我添加的新屬性是一個字符串和布爾,沒有什麼應該阻止模型反序列化。 – 2012-04-05 11:49:40

+0

Gotcha。然後做的最好的事情就是測試它 - 在仿真器上安裝舊的二進制文件,運行它等等,使用獨立的存儲工具抓取文件,安裝新的二進制文件,將舊文件放入隔離存儲器並調試它。 http://wptools.codeplex.com/ – 2012-04-05 16:18:54

+0

在我的v1.0 xap部署(通過安裝)並保存一些項目之後,我部署了v1。1(通過更新)並且數據完好無損(新屬性設置爲默認值)。我每次都用不同的數據嘗試過幾次,並且無法將數據損壞。當我從v1.1更新到v1.0時,我確實設法弄到了腐敗的唯一方法。這完全有意義,因爲屬性不會對齊。我不知道爲抱怨的顧客會發生什麼事。 – 2012-04-06 02:35:17