Tue, April 15, 2008, 01:49 AM under
Silverlight
Silverlight applications can store data (in files) onto the user's machine via the good old
Isolated Storage mechanism. The API and restrictions of Isolated Storage are slightly tweaked in the Silverlight framework. Let's explore that.
Background ResearchOn both the full (aka desktop) framework and the Silverlight framework the implementation resides in
mscorlib.dll and specifically the
System.IO.IsolatedStorage namespace. On the desktop framework the classes in there are shown on the following class diagram (with the 2 most interesting classes collapsed for exploration later):
Note that in the Silverlight implementation there is
no base abstract class
IsolatedStorage as on the desktop or
INormalizeForIsolatedStorage interface or
IsolatedStorageScope enumeration. If you explore the desktop capabilities following the links above and relate them to Silverlight's restrictions you'll see why that is – I will not explore that in this post. Also note that the
IsolatedStorageException class
is available in Silverlight.
On the flip side, when looking in the namespace in the Silvelright version of mscorlib we additionally find the
IsolatedStorageSecurityOptions enumeration that is only used by the other new type in the namespace: the
IsolatedStorageSecurityState class which itself is not used or exposed publically by anything AFAICT! So basically, just ignore these two types for now as I can only presume that someone forgot to mark them as internal.
Using ItSo back to looking at useful classes, and we are left with the 2 that exist in both variants (that are collapsed on the diagram further above):
IsolatedStorageFile and
IsolatedStorageFileStream. If you follow the links to the Silverlight documentation for those you'll find some differences compared to the desktop version and maybe the eagle-eyed among you can spot them in the following list of methods:
The
IsolatedStorageFileStream class is the same as the desktop version but it omits 5
overloads of the constructor (the ones that have a
bufferSize option and the ones that do not have the
IsolatedStorageFile argument). The
IsolatedStorageFile class has 12 static methods removed (the
GetXXX methods except one) and also adds 10 members of its own (I have marked these with an asterisk * in the screenshot above).
OK, enough of API spelunking; how do you use this thing? That's the easiest part as you just
follow the pattern of:
1. Obtaining an
IsolatedStorageFile (e.g. via the static method
GetUserStoreForApplication)
2.
Creating an
IsolatedStorageFileStream object passing it in the reference from step one
3. Creating a normal
System.IO. StreamWriter or
StreamReader passing it in the reference from step two
4. Using the
Stream to read or write as per usual.
I have a
basic SL app that uses iso storage here so have a play by entering some text/values and close/reopen the browser to see them remembered. To look at the code,
follow the steps here. To browse on your local machine to the storage, paste this in your windows explorer (and drill in to find a
moth file and a
_LocalSettings):
%userprofile%\AppData\LocalLow\Microsoft\Silverlight\is
Wait, There Is MoreWhat other things must you know? There is a default disc quota that Silverlight apps have and your app can request an increase (
IncreaseQuotaTo) from the user, but only from the UI thread. There is a
good explanation of that and more here. You may also be thinking what type of data you should be storing in iso storage (e.g. things that the browser caches anyway are not good candidates) and Chris
has some opinions here (even if some of his facts are outdated).
In addition to all of the above, Silverlight adds a unique class (no equivalent on the desktop yet) that makes it easy to store application settings in isolated store: System.IO.IsolatedStorage.
ApplicationSettings in
System.Windows.dll. There are examples of its usage
here and
here (and I also use it in my basic sample above). If you are the decompiling type, look through reflector at the class's
Save method to see how it uses the lower level APIs discussed further above combined with a
MemoryStream ;-)