Tuesday, March 13, 2012

WPF : Implement IsolatedStorageSettings in WPF

In this post I am going to implement IsolatedStorageSettings in WPF. 
Lets start with a brief introduction to IsolatedStorageSettings, Its a storage which is used for storing application configurations and it uses IsolatedStore to store those setting. Its a builtin feature in Silverlight but not available in WPF. In WPF we have ApplcationSettings , but it uses App.config to store application settings.


Why do we need IsolatedStorageSetting in WPF ?
We had a requirement where user should be able to store application setting but user will not have access to read/write any file including App.config file so we needed to be able to read write these settings at a path where users will always have access irrespective of their security settings.


Lets look at code below
1) I am going to create a new class CustomIsolatedStorageSettings which will be derived from IDictionary<string,Object>. we are deriving it from IDictionary because we want it to be like a dictionary object where we should be able to store object against their keys.


2) I am going to have use Singleton design patter to expose this class, that's why i have made private constructor and used a static constructor which initializes Instance property and also custom appDictionary object which is used to store all keys and objects.


3) I have a ReadData method which is called in static constructor , it reads file from IsolatedStorage and sets key values in appDictionary. It reads file CustomIsolatedStorage.bin which is stored in binary format and deserializes into appDictionary.



4) I have a Save method which is called whenever any key is updated. It formats appDictionary in a binary stream and saves that stream using IsolatedStorageStream in CustomIsolatedStorage.bin file.



/// <summary>
    /// This class is implemented to store user settings in an Isolated storage file.
    /// </summary>
    public class CustomIsolatedStorageSettings : IDictionary<string,Object>
    {
        #region Constants/Variables
        static Dictionary<stringobject> appDictionary = new Dictionary<stringobject>();
        static CustomIsolatedStorageSettings CustomIsolatedStorageSettings = new CustomIsolatedStorageSettings();
        const string filename = "CustomIsolatedStorage.bin";
        #endregion
 
        #region Singleton Implementation
 
        /// <summary>
        /// Its a private constructor.
        /// </summary>
        private CustomIsolatedStorageSettings()
        {
            
        }
 
        /// <summary>
        /// Its a static singleton instance.
        /// </summary>
        public static CustomIsolatedStorageSettings Instance
        {
            get
            {
                return CustomIsolatedStorageSettings;
            }
        }
 
        /// <summary>
        /// Its static constructor.
        /// </summary>
        static CustomIsolatedStorageSettings()
        {
            LoadData();
        }
 
        private static void LoadData()
        {
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, nullnull);
 
            if ( isoStore.GetFileNames(filename).Length == 0 )    
            {        
                // File not exists. Let us NOT try to DeSerialize it.        
                return;    
            }        
            
            // Read the stream from Isolated Storage.    
            Stream stream = new IsolatedStorageFileStream( filename,FileMode.OpenOrCreate, isoStore );    
            if ( stream != null )    
            {        
                try        
                {            
                    // DeSerialize the Dictionary from stream.            
                    IFormatter formatter = new BinaryFormatter();            
                    Dictionary<string,Object> appData = ( Dictionary<string,Object>) formatter.Deserialize(stream);                        
                    
                    // Enumerate through the collection and load our Dictionary.            
                    IDictionaryEnumerator enumerator = appData.GetEnumerator();            
                    while ( enumerator.MoveNext() )            
                    {
                        appDictionary[enumerator.Key.ToString()] = enumerator.Value;            
                    }        
                }        
                finally        
                {            
                    stream.Close();        
                }
    
            }
        }
 
        #endregion
 
        #region Methods
        /// <summary>
        /// It serializes dictionary in binary format and stores it in a binary file.
        /// </summary>
        public void Save()
        {
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, nullnull);
 
            Stream stream = new IsolatedStorageFileStream(filename,FileMode.Create, isoStore );
            if ( stream != null )    
            {        
                try        
                {            
                    // Serialize dictionary into the IsolatedStorage.            
                    IFormatter formatter = new BinaryFormatter();            
                    formatter.Serialize( stream, appDictionary );        
                }        
                finally        
                {            
                    stream.Close();        
                }    
            }
        }
 
        /// <summary>
        /// It Checks if Dictionary object has item corresponding to passed key,
        /// if True then it returns that object else it returns default value.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="defaultvalue"></param>
        /// <returns></returns>
        public object this[string key, Object defaultvalue]
        {
            get
            {
                if (appDictionary.ContainsKey(key))
                {
                    return appDictionary[key];
                }
                else
                {
                    return defaultvalue;
                }
            }
            set
            {
                appDictionary[key] = value;
                Save();
            }
        }
 
        #endregion
 
        #region IDictionary<string, object> Members
 
        public void Add(string key, object value)
        {
            appDictionary.Add(key, value);
            Save();
        }
 
        public bool ContainsKey(string key)
        {
            return appDictionary.ContainsKey(key);
        }
 
        public ICollection<string> Keys
        {
            get { return appDictionary.Keys; }
        }
 
        public bool Remove(string key)
        {
            try
            {
                Save();
                appDictionary.Remove(key);
                return true;
            }
            catch
            {
                return false;
            }
        }
 
        public bool TryGetValue(string key, out object value)
        {
            return appDictionary.TryGetValue(key, out value);
        }
 
        public ICollection<object> Values
        {
            get { return appDictionary.Values; }
        }
 
        public object this[string key]
        {
            get
            {
                return appDictionary[key];
            }
            set
            {
                appDictionary[key] = value;
                Save();
            }
        }
 
 
        public void Add(KeyValuePair<stringobject> item)
        {
            appDictionary.Add(item.Key, item.Value);
        }
 
        public void Clear()
        {
            appDictionary.Clear();
            Save();
        }
 
        public bool Contains(KeyValuePair<stringobject> item)
        {
            return appDictionary.ContainsKey(item.Key);
        }
 
        public void CopyTo(KeyValuePair<stringobject>[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }
 
        public int Count
        {
            get { return appDictionary.Count; }
        }
 
        public bool IsReadOnly
        {
            get { return false; }
        }
 
        public bool Remove(KeyValuePair<stringobject> item)
        {
            return appDictionary.Remove(item.Key);
        }
 
        public IEnumerator<KeyValuePair<stringobject>> GetEnumerator()
        {
            return appDictionary.GetEnumerator();    
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return appDictionary.GetEnumerator();
        }
 
        #endregion
    }










1 comment:

  1. Thank you very much, it helps me in MonoGame, where this class does not implemented

    My hack version
    http://pastebin.com/u3p7x36W

    ReplyDelete