Click here to Skip to main content
Click here to Skip to main content

Usage of IsolatedStorage Made Easy

, , 28 Jun 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Usage of IsolatedStorage made easy

Introduction

There is a very basic need to cache some data at clientside in Silverlight, when we get data using WCF service and want that data to reside at the client side so that the system will not fetch the data every time from the server. This will make sense when we know that the data is kind of static and will not change frequently.

To make use of IsolatedStorage, a developer has to create a file stream and save the data. Ideally in the real world, all data will be kept in memory as an object of some type. Now to store this object in IsolatedStorage, one has to first deserialize it and store it in files and define file names for them. Later this data will be read from the files and will be kept in memory again in the form of an object.

To simplify the above task, I have combined the functionality of IsolatedStorage and DataContractSerializer and created the ClientStorage class which helps the user to store any object directly in the IsolatedStorage, i.e. making object persistent, an interesting feature of OOPs. To achieve a feature of OOPs, one must follow the OOPs approach rather than writing the same code again and again for different objects. This piece of code can be clubbed together and I have named it as ClientStorage.

Background

Silverlight provides two classes, one is IsolatedStorage and another is DataContractSerializer.

Silverlight provides IsolatedStorage class to store data at the client machine. With isolated storage, data is isolated by user and by assembly. Credentials such as the origin or the strong name of the assembly determine assembly identity. Data can also be isolated by application domain, using similar credentials.

DataContractSerializer class is used to serialize and deserialize instances of a type into an XML stream or document. For example, you can create a type named Person with properties that contain essential data, such as a name and address. You can then create and manipulate an instance of the Person class and write all of its property values in an XML document for later retrieval, or in an XML stream for immediate transport. Most important, the DataContractSerializer is used to serialize and deserialize data sent in Silverlight version 2 messages. Apply the DataContractAttribute attribute to classes, and the DataMemberAttribute attribute to class members to specify properties and fields that are serialized.

Inside ClientStorage

ClientStorage is a singleton class that is basically a indexed collection which helps in fetching the objects on the basis of key. It automatically serializes the object and also stores the type of the object, so that it can be de-serialized later. It gives Index based object fetching mechanism which makes life easier.

It contains a Dictionary of key and object. It writes all the keys to keyNames.txt and each object in a separate file. Key names are unique so all the objects will be stored in the file name as <key_name>object.xml.

An indexer is written to fetch the value via providing the key in the index. As soon as any new key is added to the ClientStorage, it adds it to the Dictionary and serializes the Dictionary and stores it in keynames.txt file. Then the newly added object is serialized and stored in a separate file. When object is retrieved from ClientStorage, it first looks for the key existence and then if the object is null, reads the object's XML file, deserializes the object, updates in Dictionary and then returns the object.

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;
        }

While instantiating the ClientStorage object, it reads the keys file and creates the Dictionary without their objects. When retrieval request comes for any object, then only it fetches the object from the XML file. This way I am minimizing the effort of loading/instantiating the ClientStorage object.

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

The approach is simple and following the habit of using Session and ViewState. When we use Session to store any object in ASP.NET, the developer does not bother where this information will be kept. She/he keeps her/his objects in session when she wanted them to be available throughout the life time of user's session. The same applies to IsolatedStorage, when developer wants to store something per user/application wide data on client machine that would be available cross browser to the application independent of session like persistent for always until user deletes them manually. Then why to complicate things, why not something like ClientStorage[keyname] = object; and it's all done.

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

TODO

Next, it can be improved/enhanced further to provide versioning support for the objects stored in ClientStorage so that it helps in identifying the stale objects in the ClientStorage and allows to re-fetch/re-creation of that object.

I know this can be improved further, any suggestions or feedback will be highly appreciated.

History

  • 28th June, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Authors

Rohit Shrivastava
Architect
India India
No Biography provided

AmitKRana

India India
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 28 Jun 2009
Article Copyright 2009 by Rohit Shrivastava, AmitKRana
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid