65.9K
CodeProject 正在变化。 阅读更多。
Home

轻松使用 IsolatedStorage

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (10投票s)

2009 年 6 月 28 日

CPOL

4分钟阅读

viewsIcon

27100

downloadIcon

255

轻松使用 IsolatedStorage

引言

在Silverlight中,当使用WCF服务获取数据时,有一个非常基本的需求是在客户端缓存一些数据,以便数据能够保留在客户端,从而系统不必每次都从服务器获取数据。当数据是静态的并且不经常更改时,这样做是很有意义的。

为了使用IsolatedStorage,开发者必须创建一个文件流并保存数据。理想情况下,在实际应用中,所有数据都将以某种类型的对象的形式保存在内存中。现在,要将此对象存储在IsolatedStorage中,必须先将其反序列化并存储在文件中,然后为它们定义文件名。稍后,将从文件中读取这些数据,并以对象的形式重新保存在内存中。

为了简化上述任务,我结合了IsolatedStorageDataContractSerializer的功能,创建了ClientStorage类,该类帮助用户直接将任何对象存储在IsolatedStorage中,即使对象持久化,这是面向对象编程的一个有趣特性。为了实现面向对象编程的特性,必须遵循面向对象的方法,而不是为不同的对象一遍又一遍地编写相同的代码。这段代码可以组合在一起,我将其命名为ClientStorage

背景

Silverlight提供了两个类,一个是IsolatedStorage,另一个是DataContractSerializer

Silverlight提供了IsolatedStorage类来在客户端计算机上存储数据。使用隔离存储,数据会按用户和程序集进行隔离。凭据,例如程序集的来源或强名称,决定了程序集的身份。数据也可以通过类似的凭据按应用程序域进行隔离。

DataContractSerializer类用于将类型的实例序列化和反序列化为XML或文档。例如,您可以创建一个名为Person的类型,其中包含姓名和地址等基本数据的属性。然后,您可以创建和操作Person类的实例,并将其所有属性值写入XML文档以供以后检索,或写入XML流以进行即时传输。最重要的是,DataContractSerializer用于序列化和反序列化Silverlight 2版本消息中发送的数据。将DataContractAttribute属性应用于类,将DataMemberAttribute属性应用于类成员,以指定要序列化的属性和字段。

ClientStorage内部

ClientStorage是一个单例类,它基本上是一个索引集合,有助于根据键获取对象。它会自动序列化对象,并存储对象的类型,以便稍后可以对其进行反序列化。它提供了基于索引的对象获取机制,使生活更轻松。

它包含一个键和对象的Dictionary。它将所有键写入*keyNames.txt*,每个对象写入一个单独的文件。键名是唯一的,因此所有对象都将以*<key_name>object.xml*的文件名存储。

编写了一个索引器,通过提供键来获取值。一旦有任何新键添加到ClientStorage,它就会将其添加到Dictionary中,然后序列化Dictionary并将其存储在*keynames.txt*文件中。然后,新添加的对象将被序列化并存储在一个单独的文件中。当从ClientStorage检索对象时,它首先查找键是否存在,然后如果对象为null,则读取对象的XML文件,反序列化对象,更新Dictionary,然后返回对象。

private object Retreive(string key)
        {
            object value=null;

            if (CheckForFileExistence(key + KEY_OBJECT_FILE) && 
					keysNTypes.ContainsKey(key))
            {
                if (keysNTypes[key].StoredObject == null)
                {
                    try
                    {
                        using (IsolatedStorageFileStream iStream = 
			new IsolatedStorageFileStream(key + KEY_OBJECT_FILE, 
			FileMode.OpenOrCreate, isoStore))
                        {
                            if (iStream != null)
                            {
                                try
                                {
                                    DataContractSerializer serializer = 
					new DataContractSerializer
					(keysNTypes[key].TypeofObject);
                                    value = serializer.ReadObject(iStream);
                                }
                                catch (Exception)
                                {
                                    // Do nothing simply return null
                                }
                                keysNTypes[key].StoredObject = value;
                                iStream.Close();
                            }
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        throw new KeyNotFoundException();
                    }
                }
                else
                {
                    value = keysNTypes[key].StoredObject;
                }
            }
            return value;
        }

在实例化ClientStorage对象时,它会读取键文件并创建Dictionary,但没有加载对象。当检索请求到来时,它才会从XML文件中获取对象。这样,我最大限度地减少了加载/实例化ClientStorage对象的开销。

private void ReadKeys(IsolatedStorageFile isoStore)
        {
            IsolatedStorageFileStream iStream = 
		new IsolatedStorageFileStream(ISOLATED_KEY_FILE_NAME, 
              	FileMode.Open, isoStore);
            DataContractSerializer serializer = 
		new DataContractSerializer(keysNTypes.GetType());
            keysNTypes = serializer.ReadObject(iStream) as Dictionary<string>;
        }

Using the Code

该方法很简单,遵循使用SessionViewState的习惯。当我们在ASP.NET中使用Session存储任何对象时,开发人员不会关心信息将保存在哪里。当用户想要在用户会话的整个生命周期中都可用时,她/他会将她的/他的对象保存在session中。对于IsolatedStorage也是如此,当开发人员想要在客户端计算机上为每个用户/应用程序存储一些持久化数据时,这些数据将在跨浏览器中对应用程序可用,并且独立于session,就像它们一直存在直到用户手动删除它们一样。那么,为什么还要把事情搞复杂呢?为什么不使用类似ClientStorage[keyname] = object;的东西呢?这样就完成了。

// To make use of ClientStorage
ClientStorage[keyname] = object;       
object = ClientStorage[keyname];

待办事项

接下来,可以进一步改进/增强以提供ClientStorage中存储对象的版本控制支持,以便它可以帮助识别ClientStorage中的陈旧对象,并允许重新获取/重新创建该对象。

我知道这还可以进一步改进,任何建议或反馈都将不胜感激。

历史

  • 2009年6月28日:初始发布
© . All rights reserved.