Windows phone 7 WP7 IsolatedStorage XML文件在应用程序更新后为空

Windows phone 7 WP7 IsolatedStorage XML文件在应用程序更新后为空,windows-phone-7,xml-serialization,windows-phone-7.1,isolatedstorage,Windows Phone 7,Xml Serialization,Windows Phone 7.1,Isolatedstorage,我为我的WP7应用程序提交了一个更新,我的用户抱怨他们的数据在更新后被删除。我通过在IsolatedStorage中将ViewModel类序列化为XML文件来存储数据。在测试期间,我注意到更新应用程序导致设置文件被ViewModel对象的新实例(具有默认值)的序列化副本部分覆盖。我以为在写入XML文件时使用FileMode.Create解决了这个问题,但我想不是 序列化是否会出错,因为我向ViewModel对象添加了新属性,并且从现有XML文件反序列化失败?如果无法从XML文件中读取新的View

我为我的WP7应用程序提交了一个更新,我的用户抱怨他们的数据在更新后被删除。我通过在IsolatedStorage中将ViewModel类序列化为XML文件来存储数据。在测试期间,我注意到更新应用程序导致设置文件被ViewModel对象的新实例(具有默认值)的序列化副本部分覆盖。我以为在写入XML文件时使用FileMode.Create解决了这个问题,但我想不是

序列化是否会出错,因为我向ViewModel对象添加了新属性,并且从现有XML文件反序列化失败?如果无法从XML文件中读取新的ViewModel对象,则我的代码设置为实例化新的ViewModel对象。如果是这种情况,是否意味着我无法向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; }
}
公共类MyClass:INotifyPropertyChanged
{
公共MyClass()
{
//设置默认值
this.Items=新的ObservableCollection();
this.TextTemplate=“默认”;
this.HasSeenSomething=false;
}
公共ObservableCollection项{get;set;}
//应用程序更新中添加的新属性
公共字符串TextTemplate{get;set;}
公共布尔值{get;set;}
}
下面是我用来序列化/反序列化ViewModel的代码。我认为这是相当标准的,但也许我搞砸了:

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;
}
publicstaticvoidwritetoxml(T数据,字符串路径)
{
var xmlWriterSettings=new xmlWriterSettings{Indent=true};
使用(var myIsolatedStorage=IsolatedStorageFile.GetUserStoreForApplication())
{
使用(var stream=myIsolatedStorage.OpenFile(路径,FileMode.Create))
{
var serializer=newxmlserializer(typeof(T));
使用(var xmlWriter=xmlWriter.Create(stream,xmlWriterSettings))
{
serializer.Serialize(xmlWriter,数据);
}
}
}
}
公共静态T ReadFromXml(字符串路径)
{
T数据=默认值(T);
尝试
{
使用(var myIsolatedStorage=IsolatedStorageFile.GetUserStoreForApplication())
{
if(myIsolatedStorage.FileExists(path))
{
使用(var stream=myIsolatedStorage.OpenFile(路径,FileMode.Open))
{
尝试
{
var serializer=newxmlserializer(typeof(T));
对象实例=序列化程序。反序列化(流);
如果(实例!=null)数据=(T)实例;
}
catch(System.Exception-ex)
{
var e=ex;
}
}
}
}
}
catch(System.Exception-ex)
{
var e=ex;
}
返回数据;
}

您可以,但有一些问题

  • 您需要确保更改属性的方式不会在反序列化时中断。所以将Int改为String是可以的(虽然我不建议),但是相反的情况可能会破坏
  • 您需要记住,当您反序列化对象时,不会调用ctor。这意味着,如果您在ctor中执行以下操作:

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

  • 如果集合为null,那么当您第一次尝试访问该属性时,您将在NullRef上死亡

    一毛钱换一美元,我敢打赌你一定是在打第二点

    修复它相当容易,但是你需要记住去做。这些选择包括:

  • 在属性访问器中,检查支持字段是否为null,如果为null,则实例化它
  • 创建一个函数(
    public
    ),该函数具有修饰它的
    [OnDeserialized]
    属性。反序列化完成后,该代码将运行,您可以在那里实例化您的成员

  • 我不认为空集合是问题所在。集合中会有数据,否则用户不会丢失任何东西。我添加的新属性是一个字符串和bool,不应该阻止模型反序列化。明白了。最好的方法就是测试它——在模拟器上安装旧的二进制文件,运行它,等等,使用一个独立的存储工具获取文件,安装新的二进制文件,将旧文件放在独立的存储中并调试它。在将(通过安装)我的v1.0 xap部署到我的设备并保存一些项目后,我部署了v1.1(通过更新),数据保持完整(新属性设置为默认值)。我尝试了几次,每次都使用不同的数据,但都没有损坏数据。我从v1.1升级到v1.0时,是唯一一种能够获得损坏的方法。这完全有道理,因为属性不会对齐。我不知道投诉的客户会发生什么。数据会有多大?我的应用程序采用了“备份和保存”机制,以确保我不会在保存过程中意外丢失崩溃数据或在保存过程中强制关闭应用程序。你可能想做一些类似的事情。即使他们有一个相当大的项目集合,数据的大小也不会那么大,因为它大部分都是整数。我认为在保存之前添加备份副本是一个好主意,我将在我的应用程序中实现这一点。谢谢你的建议。