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