ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 【Silverlight】利用IsolatedStorageFile实现客户端缓存

【Silverlight】利用IsolatedStorageFile实现客户端缓存

原创 Linux操作系统 作者:iDotNetSpace 时间:2009-07-31 10:30:07 0 删除 编辑

为将一套系统局部改版为BS应用,最近在琢磨Silverlight,发现这玩意可能真能带来一场革命,对于程序员来说比Flash好的还真不是一星半点。

废话就不说了,来点实在的。我们有些数据,特别是些不是经常变的数据往往需要进行缓存,以往在asp.net的时候使用page的cache属性,其实那还是存放在服务器端,对服务器压力比较大,这下好了silverlight提供了IsolatedStorageFile,而且可以申请无限量空间,当然是要人家客户端同意了,实现也很简单


        /// 
        
/// 在客户端申请存储空间
        
/// 

        
/// 空间大小(KB)
        
/// 
        public static bool ApplyStorageSpace(double size)
        {
            
try
            {
                
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    Int64 newQuotaSize 
= Convert.ToInt64(size * 1024); //换算为字节
                    Int64 curAvail = store.AvailableFreeSpace;

                    
if (curAvail < newQuotaSize)
                    {
                        
if (!store.IncreaseQuotaTo(newQuotaSize))
                            
return false;
                        
else
                            
return true;
                    }
                    
else
                    {
                        
return true;
                    }
                }
            }
            
catch (IsolatedStorageException ex)
            {
                
throw ex;
            }
        }

看到这个东西自然而然就想到了,用来做缓存和离线数据存储肯定能成,于是找了下老外的做法(silverlight还是老外用的多啊)找个个不错的类,简单改了改就很好用了


/// 
    
/// Client Storage class for storing objects in IsolatedStorage
    
/// 

    public class ClientStorage
    {
        
#region Constants

        
const string ISOLATED_KEY_FILE_NAME = "KeyNames.txt";
        
const string KEY_OBJECT_FILE = "object.xml";

        
#endregion

        
#region Private Static Fields

        IsolatedStorageFile isoStore 
= IsolatedStorageFile.GetUserStoreForApplication();
        Dictionary
<string, TypeAndValue> keysNTypes;

        
#endregion

        
#region CTOR
        
/// 
        
/// private CTOR to initialize the class to make it singleton
        
/// 

        private ClientStorage()
        {
            keysNTypes 
= new Dictionary<string, TypeAndValue>();
            
if (FileExists(ISOLATED_KEY_FILE_NAME))
            {
                ReadKeys(isoStore);
            }
        }

        
/// 
        
/// Nested class for lazy initialization.
        
/// 

        class NestedClientStorage
        {
            
// Explicit static constructor to tell C# compiler
            
// not to mark type as beforefieldinit
            static NestedClientStorage()
            {
            }
            
internal static readonly ClientStorage Instance = new ClientStorage();
        }
        
#endregion

        
#region Private Helper Methods

        
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, TypeAndValue>;
            iStream.Close();
        }

        
private void AddKey(string key, object value)
        {
            
if (!keysNTypes.ContainsKey(key))
                keysNTypes.Add(key, 
new TypeAndValue());
            keysNTypes[key].TypeofObject 
= value.GetType();
            keysNTypes[key].StoredObject 
= value;
            WriteKeyFile();
        }

        
private void WriteKeyFile()
        {
            
using (IsolatedStorageFileStream oStream = new IsolatedStorageFileStream(ISOLATED_KEY_FILE_NAME,
                                                        FileMode.Create, isoStore))
            {
                DataContractSerializer serializer 
= new DataContractSerializer(keysNTypes.GetType());

                serializer.WriteObject(oStream, keysNTypes);
                oStream.Close();
            }
        }

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

            
if (FileExists(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 retrun null
                                }
                                keysNTypes[key].StoredObject 
= value;
                                iStream.Close();
                            }
                        }
                    }
                    
catch (FileNotFoundException)
                    {
                        
throw new KeyNotFoundException();
                    }
                }
                
else
                {
                    value 
= keysNTypes[key].StoredObject;
                }
            }
            
return value;
        }

        
private void AddOrUpdate(string key, object value)
        {
            
try
            {
                IsolatedStorageFileStream oStream 
= new IsolatedStorageFileStream(key + KEY_OBJECT_FILE,
                                                    FileMode.Create, isoStore);
                DataContractSerializer serializer 
= new DataContractSerializer(value.GetType());

                serializer.WriteObject(oStream, value);

                oStream.Close();
            }
            
catch (IsolatedStorageException)
            {
                
if (ApplyStorageSpace(1024 * 1024 * 1024))
                {
                    AddOrUpdate(key, value);
                }
            }
            
        }

        
private void Add(string key, object value, bool throwErrorOnDuplicate)
        {
            
if (keysNTypes.ContainsKey(key) && throwErrorOnDuplicate)
            {
                
throw new System.Exception("Duplicate key provided.");
            }
            
else
            {
                AddKey(key, value);
                AddOrUpdate(key, value);
            }
        }

        
private bool FileExists(string fileName)
        {
            
return isoStore.FileExists(fileName);
        }
        
#endregion

        
#region Public Methods
        
/// 
        
/// Public static property to get the instance of ClientStorage which is a singleton class
        
/// 

        public static ClientStorage Instance
        {
            
get
            {
                
return NestedClientStorage.Instance;
            }
        }

        
///  
        
/// Adds a key/value to the storage device. 
        
/// 
 
        
/// Key to identify the object 
        
/// Version Number
        
/// Value as object 
        public void Add(string key, object value)
        {
            Add(key, value, 
true);
        }

        
/// 
        
/// Remove a element from the Isolated Storage
        
/// 

        
/// key
        public void Remove(string key)
        {
            keysNTypes.Remove(key);
            WriteKeyFile();
            
if (FileExists(key + KEY_OBJECT_FILE))
            {
                isoStore.DeleteFile(key 
+ KEY_OBJECT_FILE);
            }

        }

        
/// 
        
/// Indexer for CLientStorage
        
/// 

        
/// Key
        
///  Version Number
        
/// returns the object on the basis of key
        public object this[string key]
        {
            
get
            {
                
return Retreive(key);
            }
            
set
            {
                Add(key, value, 
false);
            }
        }

        
/// 
        
/// 在客户端申请存储空间
        
/// 

        
/// 空间大小(KB)
        
/// 
        public static bool ApplyStorageSpace(double size)
        {
            
try
            {
                
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    Int64 newQuotaSize 
= Convert.ToInt64(size * 1024); //换算为字节
                    Int64 curAvail = store.AvailableFreeSpace;

                    
if (curAvail < newQuotaSize)
                    {
                        
if (!store.IncreaseQuotaTo(newQuotaSize))
                            
return false;
                        
else
                            
return true;
                    }
                    
else
                    {
                        
return true;
                    }
                }
            }
            
catch (IsolatedStorageException ex)
            {
                
throw ex;
            }
        }
        
#endregion

        
#region TypeAndValue

        [DataContract]
        
public class TypeAndValue
        {
            
public TypeAndValue()
            {
            }

            
public Type TypeofObject { getset; }
            
public object StoredObject { getset; }

            
private string fullyQualifiedTypeName;

            [DataMember]
            
public string FullyQualifiedTypeName
            {
                
get
                {
                    
if (fullyQualifiedTypeName == null)
                    {
                        fullyQualifiedTypeName 
= TypeofObject.AssemblyQualifiedName;
                    }
                    
return fullyQualifiedTypeName;
                }
                
set
                {
                    fullyQualifiedTypeName 
= value;
                    TypeofObject 
= Type.GetType(fullyQualifiedTypeName);
                }
            }
        }
        
#endregion
    }

本来用来做缓存这个就够用了,但为了能进一步使用方便,还是做了件多余的事就是在这个基础上再封了个Cache类这样用起来可能就更直观了



namespace SilverlightCache
{
    
public class Cache
    {
        Cache() 
        {
        }

        
/// 
        
/// Nested class for lazy initialization.
        
/// 

        class NestedCache
        {
            
// Explicit static constructor to tell C# compiler
            
// not to mark type as beforefieldinit
            static NestedCache()
            {
            }
            
internal static readonly Cache Instance = new Cache();
        }

        
public static Cache Instance
        {
            
get { return NestedCache.Instance; }
        }

        
public object this[string key]
        {
            
get { return ClientStorage.Instance[key]; }
            
set { ClientStorage.Instance[key] = value; }
        }

        
public void Remove(string key)
        {
            ClientStorage.Instance.Remove(key);
        }

    }
}

用法也超简单,例程假设的是从服务取数据,然后缓存到客户端,下次使用时不再访问服务即可,当然如果用户清理了IsolatedStorage就要重新取服务上的数据了


public partial class MainPage : UserControl
    {
        Service1Client client 
= new Service1Client();
        
const string KEY_CACHE = "key_cache";

        
public MainPage()
        {
            InitializeComponent();
            client.DoWorkCompleted 
+= new EventHandler<DoWorkCompletedEventArgs>(client_DoWorkCompleted);
        }

        
void client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
        {
            Cache.Instance[KEY_CACHE] 
= e.Result;
            Message(
"Service""List's count:"+e.Result.Count().ToString());
        }

        
private void btnTest_Click(object sender, RoutedEventArgs e)
        {
            
if (Cache.Instance[KEY_CACHE] == null)
            {
                client.DoWorkAsync();
            }
            
else
            {
                Message(
"Cache""List's count:" + (Cache.Instance[KEY_CACHE] as ObservableCollection<Something>).Count().ToString());
            }
        }

        
void Message(string from, string msg)
        {
            MessageBox.Show(
string.Format("Data from {0}, msg is {1}", from, msg));
        }
    }

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-610957/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-01-04

  • 博文量
    2376
  • 访问量
    5304451