C# 在隔离存储设置中存储对象

C# 在隔离存储设置中存储对象,c#,silverlight,windows-phone-7,object,isolatedstorage,C#,Silverlight,Windows Phone 7,Object,Isolatedstorage,我有一个对象要存储在IsolatedStorageSettings中,当应用程序重新启动时,我不想重用它 我的问题在于,我出于某种原因编写的代码在重新启动密钥时试图访问该对象时不记得该对象 namespace MyNameSpace { public class WindowsPhoneSettings { private const string SelectedSiteKey = "SelectedSite"; private Isolated

我有一个对象要存储在IsolatedStorageSettings中,当应用程序重新启动时,我不想重用它

我的问题在于,我出于某种原因编写的代码在重新启动密钥时试图访问该对象时不记得该对象

namespace MyNameSpace
{
    public class WindowsPhoneSettings
    {
        private const string SelectedSiteKey = "SelectedSite";
        private IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;

        private T RetrieveSetting<T>(string settingKey)
        {
            object settingValue;
            if (isolatedStore.TryGetValue(settingKey, out settingValue))
            {
                return (T)settingValue;
            }
            return default(T);
        }

        public bool AddOrUpdateValue(string Key, Object value)
        {
            bool valueChanged = false;

            if (isolatedStore.Contains(Key))
            {
                if (isolatedStore[Key] != value)
                {
                    isolatedStore[Key] = value;
                    valueChanged = true;
                }
            }
            else
            {
                isolatedStore.Add(Key, value);
                valueChanged = true;
            }
            return valueChanged;
        }

        public MobileSiteDataModel SelectedSite
        {
            get
            {
                return RetrieveSetting<MobileSiteDataModel>(SelectedSiteKey);
            }
            set
            {
                AddOrUpdateValue(SelectedSiteKey, value);
                isolatedStore.Save();
            }
        }
    }
}
名称空间MyNameSpace
{
公共类WindowsPhoneSettings
{
私有常量字符串SelectedSiteKey=“SelectedSite”;
私有隔离存储设置隔离存储=隔离存储设置。应用程序设置;
私有T RetrieveSetting(字符串设置密钥)
{
对象设置值;
if(isolatedStore.TryGetValue(设置键,输出设置值))
{
返回(T)设定值;
}
返回默认值(T);
}
public bool AddOrUpdateValue(字符串键,对象值)
{
bool valueChanged=false;
if(isolatedStore.Contains(键))
{
if(isolatedStore[键]!=值)
{
isolatedStore[键]=值;
valueChanged=true;
}
}
其他的
{
添加(键,值);
valueChanged=true;
}
返回值已更改;
}
公共移动数据模型选定站点
{
得到
{
返回检索设置(SelectedSiteKey);
}
设置
{
AddOrUpdateValue(SelectedSiteKey,值);
isolatedStore.Save();
}
}
}
}
然后我在App.xaml.cs中实例化WindowsPhoneSettings,并为其创建一个公共getter和setter。能够在整个应用程序中访问它。调试结果表明,正确的对象存储在隔离存储中,但关闭应用程序并重新打开时,隔离存储似乎为空。我在模拟器和真实设备上都试过了。如您所见,在设置对象时,我确实调用了save方法


我在这里做错了什么?

如果您将
检索设置更改为:

private T RetrieveSetting<T>(string settingKey)
{
  T settingValue;
  if(isolatedStore.TryGetValue(settingKey, out settingValue))
  {
    return (T)settingValue;
  }
  return default(T);
}
private T retrieveset(字符串设置键)
{
T设定值;
if(isolatedStore.TryGetValue(设置键,输出设置值))
{
返回(T)设定值;
}
返回默认值(T);
}

请注意,正在获取的对象被声明为类型
T
,而不是
object

存储在隔离存储设置中的对象是使用序列化的,因此必须是可序列化的。确保在添加到ISS之前(以及从ISS中删除之后),可以自己对其进行序列化(和反序列化)


如果在尝试检索时项目不存在,则可能是因为无法首先添加它们(由于序列化问题)。

我最终将设置保存到隔离存储中的一个文件中,因为隔离存储设置似乎从未工作过

所以我的代码是这样的:

public class PhoneSettings
{
    private const string SettingsDir = "settingsDir";
    private const string SettingsFile = "settings.xml";

    public void SetSettings(Settings settings)
    {
        SaveSettingToFile<Settings>(SettingsDir, SettingsFile, settings);
    }

    public Settings GetSettings()
    {
        return RetrieveSettingFromFile<Settings>(SettingsDir, SettingsFile);
    }

    private T RetrieveSettingFromFile<T>(string dir, string file) where T : class
    {
        IsolatedStorageFile isolatedFileStore = IsolatedStorageFile.GetUserStoreForApplication();
        if (isolatedFileStore.DirectoryExists(dir))
        {
            try
            {
                using (var stream = new IsolatedStorageFileStream(System.IO.Path.Combine(dir, file), FileMode.Open, isolatedFileStore))
                {
                    return (T)SerializationHelper.DeserializeData<T>(stream);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Could not retrieve file " + dir + "\\" + file + ". With Exception: " + ex.Message);
            }
        }
        return null;
    }

    private void SaveSettingToFile<T>(string dir, string file, T data)
    {
        IsolatedStorageFile isolatedFileStore = IsolatedStorageFile.GetUserStoreForApplication();
        if (!isolatedFileStore.DirectoryExists(dir))
            isolatedFileStore.CreateDirectory(dir);
        try
        {
            string fn = System.IO.Path.Combine(dir, file);
            if (isolatedFileStore.FileExists(fn)) isolatedFileStore.DeleteFile(fn); //mostly harmless, used because isolatedFileStore is stupid :D

            using (var stream = new IsolatedStorageFileStream(fn, FileMode.CreateNew, FileAccess.ReadWrite, isolatedFileStore))
            {
                SerializationHelper.SerializeData<T>(data, stream);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("Could not save file " + dir + "\\" + file + ". With Exception: " + ex.Message);
        }
    }
}
编辑:如何实现
SerializationHelper
的示例

public static class SerializationHelper
{
    public static void SerializeData<T>(this T obj, Stream streamObject)
    {
        if (obj == null || streamObject == null)
            return;

        var ser = new DataContractJsonSerializer(typeof(T));
        ser.WriteObject(streamObject, obj);
    }

    public static T DeserializeData<T>(Stream streamObject)
    {
        if (streamObject == null)
            return default(T);

        var ser = new DataContractJsonSerializer(typeof(T));
        return (T)ser.ReadObject(streamObject);
    }
}
公共静态类SerializationHelper
{
公共静态无效序列化数据(此T对象,streamObject)
{
if(obj==null | | streamObject==null)
返回;
var ser=新数据契约JSONSerializer(类型(T));
ser.WriteObject(streamObject,obj);
}
公共静态T反序列化数据(streamObject)
{
if(streamObject==null)
返回默认值(T);
var ser=新数据契约JSONSerializer(类型(T));
返回(T)序列读取对象(streamObject);
}
}

以下是我用来将对象保存到独立存储和从独立存储加载对象的代码-

private void saveToIsolatedStorage(string keyname, object value)
{
  IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;
  isolatedStore.Remove(keyname);
  isolatedStore.Add(keyname, value);
  isolatedStore.Save();
}

private bool loadObject(string keyname, out object result)
{
  IsolatedStorageSettings isolatedStore = IsolatedStorageSettings.ApplicationSettings;

  result = null;
  try
  {
    result = isolatedStore[keyname];
  }
  catch
  {
    return false;
  }
  return true;
}
下面是我用来调用上面的代码-

private void SaveToIsolatedStorage()
{
  saveToIsolatedStorage("GameData", GameData);
}

private void LoadFromIsolatedStorage()
{
  Object temp;
  if (loadObject("GameData", out temp))
  {
    GameData = (CGameData)temp;
  }
  else
  {
    GameData.Reset();
  }
}

请注意,我像这样保存和恢复的对象很小并且可以序列化。如果我的对象包含二维数组或其他不可序列化的对象,则在使用iso存储之前,我会执行自己的序列化和反序列化。

这没有帮助。正如在问题中试图说的,当使用调试器单步执行时,IsolatedStorage根本不包含任何键。@Cheesebaron您是否使用Rebuild all来生成项目?或者使用应用程序部署工具部署XAP文件?这两个操作都会卸载并重新安装现有的应用程序,从而清除孤立的存储。使用Build选项并在VisualStudio中单击F5。如果我自己序列化该对象并将其放入IsolatedStorageFile中,则可以正常工作。只需使用XmlSerializer即可完成此操作,并且不会修改我尝试序列化的对象。在保存到ISS之前,我不确定如何序列化和反序列化对象,请提供一些提供更多信息的链接,最好是一个示例。什么是SerializationHelper?是其他图书馆的吗?如果是的话,请提一下。SerializationHelper只是一个简单的类,负责序列化和反序列化对象。在本例中,我的一位同事编写了一些东西,因为我们使用的实现还需要对压缩和解压缩文件的支持。尽管您可以使用默认的
System.Xml.Serialization
方法或一些JSON序列化程序,但添加了一个使用JSON的SerializationHelper示例。我在这里遇到了相同的问题。字符串、布尔值或整数等简单对象可以轻松保存。但是,如果我试图保存一个Song对象,则在重新启动时,所有内容(包括其他值)似乎都会被删除,而不会显示任何错误消息。这可能是一些奇怪的bug,我认为这是一个内部序列化问题。
private void SaveToIsolatedStorage()
{
  saveToIsolatedStorage("GameData", GameData);
}

private void LoadFromIsolatedStorage()
{
  Object temp;
  if (loadObject("GameData", out temp))
  {
    GameData = (CGameData)temp;
  }
  else
  {
    GameData.Reset();
  }
}