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

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

ApplyStorageSpace
  1.         /// <summary>
  2.         /// 在客户端申请存储空间
  3.         /// </summary>
  4.         /// <param name="size">空间大小(KB)</param>
  5.         /// <returns></returns>
  6.         public static bool ApplyStorageSpace(double size)
  7.         {
  8.             try
  9.             {
  10.                 using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  11.                 {
  12.                     Int64 newQuotaSize = Convert.ToInt64(size * 1024); //换算为字节
  13.                     Int64 curAvail = store.AvailableFreeSpace;

  14.                     if (curAvail < newQuotaSize)
  15.                     {
  16.                         if (!store.IncreaseQuotaTo(newQuotaSize))
  17.                             return false;
  18.                         else
  19.                             return true;
  20.                     }
  21.                     else
  22.                     {
  23.                         return true;
  24.                     }
  25.                 }
  26.             }
  27.             catch (IsolatedStorageException ex)
  28.             {
  29.                 throw ex;
  30.             }
  31.         }
复制代码
看到这个东西自然而然就想到了,用来做缓存和离线数据存储肯定能成,于是找了下老外的做法(silverlight还是老外用的多啊)找个个不错的类,简单改了改就很好用了

ClientStorage
  1. /// <summary>
  2.     /// Client Storage class for storing objects in IsolatedStorage
  3.     /// </summary>
  4.     public class ClientStorage
  5.     {
  6.         #region Constants

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

  9.         #endregion

  10.         #region Private Static Fields

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

  13.         #endregion

  14.         #region CTOR
  15.         /// <summary>
  16.         /// private CTOR to initialize the class to make it singleton
  17.         /// </summary>
  18.         private ClientStorage()
  19.         {
  20.             keysNTypes = new Dictionary<string, TypeAndValue>();
  21.             if (FileExists(ISOLATED_KEY_FILE_NAME))
  22.             {
  23.                 ReadKeys(isoStore);
  24.             }
  25.         }

  26.         /// <summary>
  27.         /// Nested class for lazy initialization.
  28.         /// </summary>
  29.         class NestedClientStorage
  30.         {
  31.             // Explicit static constructor to tell C# compiler
  32.             // not to mark type as beforefieldinit
  33.             static NestedClientStorage()
  34.             {
  35.             }
  36.             internal static readonly ClientStorage Instance = new ClientStorage();
  37.         }
  38.         #endregion

  39.         #region Private Helper Methods

  40.         private void ReadKeys(IsolatedStorageFile isoStore)
  41.         {
  42.             IsolatedStorageFileStream iStream = new IsolatedStorageFileStream(ISOLATED_KEY_FILE_NAME,
  43.                                                                     FileMode.Open, isoStore);
  44.             DataContractSerializer serializer = new DataContractSerializer(keysNTypes.GetType());
  45.             keysNTypes = serializer.ReadObject(iStream) as Dictionary<string, TypeAndValue>;
  46.             iStream.Close();
  47.         }

  48.         private void AddKey(string key, object value)
  49.         {
  50.             if (!keysNTypes.ContainsKey(key))
  51.                 keysNTypes.Add(key, new TypeAndValue());
  52.             keysNTypes[key].TypeofObject = value.GetType();
  53.             keysNTypes[key].StoredObject = value;
  54.             WriteKeyFile();
  55.         }

  56.         private void WriteKeyFile()
  57.         {
  58.             using (IsolatedStorageFileStream oStream = new IsolatedStorageFileStream(ISOLATED_KEY_FILE_NAME,
  59.                                                         FileMode.Create, isoStore))
  60.             {
  61.                 DataContractSerializer serializer = new DataContractSerializer(keysNTypes.GetType());

  62.                 serializer.WriteObject(oStream, keysNTypes);
  63.                 oStream.Close();
  64.             }
  65.         }

  66.         private object Retreive(string key)
  67.         {
  68.             object value = null;

  69.             if (FileExists(key + KEY_OBJECT_FILE) && keysNTypes.ContainsKey(key))
  70.             {
  71.                 if (keysNTypes[key].StoredObject == null)
  72.                 {
  73.                     try
  74.                     {
  75.                         using (IsolatedStorageFileStream iStream = new IsolatedStorageFileStream(key + KEY_OBJECT_FILE, FileMode.OpenOrCreate, isoStore))
  76.                         {
  77.                             if (iStream != null)
  78.                             {
  79.                                 try
  80.                                 {
  81.                                     DataContractSerializer serializer = new DataContractSerializer(keysNTypes[key].TypeofObject);
  82.                                     value = serializer.ReadObject(iStream);
  83.                                 }
  84.                                 catch (Exception)
  85.                                 {
  86.                                     // Do nothing simply retrun null
  87.                                 }
  88.                                 keysNTypes[key].StoredObject = value;
  89.                                 iStream.Close();
  90.                             }
  91.                         }
  92.                     }
  93.                     catch (FileNotFoundException)
  94.                     {
  95.                         throw new KeyNotFoundException();
  96.                     }
  97.                 }
  98.                 else
  99.                 {
  100.                     value = keysNTypes[key].StoredObject;
  101.                 }
  102.             }
  103.             return value;
  104.         }

  105.         private void AddOrUpdate(string key, object value)
  106.         {
  107.             try
  108.             {
  109.                 IsolatedStorageFileStream oStream = new IsolatedStorageFileStream(key + KEY_OBJECT_FILE,
  110.                                                     FileMode.Create, isoStore);
  111.                 DataContractSerializer serializer = new DataContractSerializer(value.GetType());

  112.                 serializer.WriteObject(oStream, value);

  113.                 oStream.Close();
  114.             }
  115.             catch (IsolatedStorageException)
  116.             {
  117.                 if (ApplyStorageSpace(1024 * 1024 * 1024))
  118.                 {
  119.                     AddOrUpdate(key, value);
  120.                 }
  121.             }
  122.            
  123.         }

  124.         private void Add(string key, object value, bool throwErrorOnDuplicate)
  125.         {
  126.             if (keysNTypes.ContainsKey(key) && throwErrorOnDuplicate)
  127.             {
  128.                 throw new System.Exception("Duplicate key provided.");
  129.             }
  130.             else
  131.             {
  132.                 AddKey(key, value);
  133.                 AddOrUpdate(key, value);
  134.             }
  135.         }

  136.         private bool FileExists(string fileName)
  137.         {
  138.             return isoStore.FileExists(fileName);
  139.         }
  140.         #endregion

  141.         #region Public Methods
  142.         /// <summary>
  143.         /// Public static property to get the instance of ClientStorage which is a singleton class
  144.         /// </summary>
  145.         public static ClientStorage Instance
  146.         {
  147.             get
  148.             {
  149.                 return NestedClientStorage.Instance;
  150.             }
  151.         }

  152.         /// <summary>
  153.         /// Adds a key/value to the storage device.
  154.         /// </summary>
  155.         /// <param name="key">Key to identify the object</param>
  156.         /// <param name="versionNumber">Version Number</param>
  157.         /// <param name="value">Value as object</param>
  158.         public void Add(string key, object value)
  159.         {
  160.             Add(key, value, true);
  161.         }

  162.         /// <summary>
  163.         /// Remove a element from the Isolated Storage
  164.         /// </summary>
  165.         /// <param name="key">key</param>
  166.         public void Remove(string key)
  167.         {
  168.             keysNTypes.Remove(key);
  169.             WriteKeyFile();
  170.             if (FileExists(key + KEY_OBJECT_FILE))
  171.             {
  172.                 isoStore.DeleteFile(key + KEY_OBJECT_FILE);
  173.             }

  174.         }

  175.         /// <summary>
  176.         /// Indexer for CLientStorage
  177.         /// </summary>
  178.         /// <param name="key">Key</param>
  179.         /// <param name="versionNumber"> Version Number</param>
  180.         /// <returns>returns the object on the basis of key</returns>
  181.         public object this[string key]
  182.         {
  183.             get
  184.             {
  185.                 return Retreive(key);
  186.             }
  187.             set
  188.             {
  189.                 Add(key, value, false);
  190.             }
  191.         }

  192.         /// <summary>
  193.         /// 在客户端申请存储空间
  194.         /// </summary>
  195.         /// <param name="size">空间大小(KB)</param>
  196.         /// <returns></returns>
  197.         public static bool ApplyStorageSpace(double size)
  198.         {
  199.             try
  200.             {
  201.                 using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  202.                 {
  203.                     Int64 newQuotaSize = Convert.ToInt64(size * 1024); //换算为字节
  204.                     Int64 curAvail = store.AvailableFreeSpace;

  205.                     if (curAvail < newQuotaSize)
  206.                     {
  207.                         if (!store.IncreaseQuotaTo(newQuotaSize))
  208.                             return false;
  209.                         else
  210.                             return true;
  211.                     }
  212.                     else
  213.                     {
  214.                         return true;
  215.                     }
  216.                 }
  217.             }
  218.             catch (IsolatedStorageException ex)
  219.             {
  220.                 throw ex;
  221.             }
  222.         }
  223.         #endregion

  224.         #region TypeAndValue

  225.         [DataContract]
  226.         public class TypeAndValue
  227.         {
  228.             public TypeAndValue()
  229.             {
  230.             }

  231.             public Type TypeofObject { get; set; }
  232.             public object StoredObject { get; set; }

  233.             private string fullyQualifiedTypeName;

  234.             [DataMember]
  235.             public string FullyQualifiedTypeName
  236.             {
  237.                 get
  238.                 {
  239.                     if (fullyQualifiedTypeName == null)
  240.                     {
  241.                         fullyQualifiedTypeName = TypeofObject.AssemblyQualifiedName;
  242.                     }
  243.                     return fullyQualifiedTypeName;
  244.                 }
  245.                 set
  246.                 {
  247.                     fullyQualifiedTypeName = value;
  248.                     TypeofObject = Type.GetType(fullyQualifiedTypeName);
  249.                 }
  250.             }
  251.         }
  252.         #endregion
  253.     }
复制代码
本来用来做缓存这个就够用了,但为了能进一步使用方便,还是做了件多余的事就是在这个基础上再封了个Cache类这样用起来可能就更直观了

Cache
  1. namespace SilverlightCache
  2. {
  3.     public class Cache
  4.     {
  5.         Cache()
  6.         {
  7.         }

  8.         /// <summary>
  9.         /// Nested class for lazy initialization.
  10.         /// </summary>
  11.         class NestedCache
  12.         {
  13.             // Explicit static constructor to tell C# compiler
  14.             // not to mark type as beforefieldinit
  15.             static NestedCache()
  16.             {
  17.             }
  18.             internal static readonly Cache Instance = new Cache();
  19.         }

  20.         public static Cache Instance
  21.         {
  22.             get { return NestedCache.Instance; }
  23.         }

  24.         public object this[string key]
  25.         {
  26.             get { return ClientStorage.Instance[key]; }
  27.             set { ClientStorage.Instance[key] = value; }
  28.         }

  29.         public void Remove(string key)
  30.         {
  31.             ClientStorage.Instance.Remove(key);
  32.         }

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

Usage
  1. public partial class MainPage : UserControl
  2.     {
  3.         Service1Client client = new Service1Client();
  4.         const string KEY_CACHE = "key_cache";

  5.         public MainPage()
  6.         {
  7.             InitializeComponent();
  8.             client.DoWorkCompleted += new EventHandler<DoWorkCompletedEventArgs>(client_DoWorkCompleted);
  9.         }

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

  15.         private void btnTest_Click(object sender, RoutedEventArgs e)
  16.         {
  17.             if (Cache.Instance[KEY_CACHE] == null)
  18.             {
  19.                 client.DoWorkAsync();
  20.             }
  21.             else
  22.             {
  23.                 Message("Cache", "List's count:" + (Cache.Instance[KEY_CACHE] as ObservableCollection<Something>).Count().ToString());
  24.             }
  25.         }

  26.         void Message(string from, string msg)
  27.         {
  28.             MessageBox.Show(string.Format("Data from {0}, msg is {1}", from, msg));
  29.         }
  30.     }
复制代码
DEMO下载:
附件: 亲,您没有权限下载或查看附件喔:-) 试试登录注册吧!
TOP

fdsafafafa
TOP

asdfasdfasdfasdf
TOP

thank you
TOP

Thank you
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP

深情顶帖,楼主加油!
TOP