轻松使用 IsolatedStorage






4.50/5 (10投票s)
轻松使用 IsolatedStorage
引言
在Silverlight中,当使用WCF服务获取数据时,有一个非常基本的需求是在客户端缓存一些数据,以便数据能够保留在客户端,从而系统不必每次都从服务器获取数据。当数据是静态的并且不经常更改时,这样做是很有意义的。
为了使用IsolatedStorage
,开发者必须创建一个文件流并保存数据。理想情况下,在实际应用中,所有数据都将以某种类型的对象的形式保存在内存中。现在,要将此对象存储在IsolatedStorage
中,必须先将其反序列化并存储在文件中,然后为它们定义文件名。稍后,将从文件中读取这些数据,并以对象的形式重新保存在内存中。
为了简化上述任务,我结合了IsolatedStorage
和DataContractSerializer
的功能,创建了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
该方法很简单,遵循使用Session
和ViewState
的习惯。当我们在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日:初始发布