【Silverlight】利用IsolatedStorageFile實現客戶端快取
為將一套系統區域性改版為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
///
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 { get; set; }
public object StoredObject { get; set; }
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Silverlight中利用WCF獲取客戶端IP客戶端
- 在 WPF 客戶端實現 AOP 和介面快取客戶端快取
- Redis 6.0 客戶端快取的伺服器端實現Redis客戶端快取伺服器
- 億級流量客戶端快取之Http快取與本地快取對比客戶端快取HTTP
- 利用tirpc庫實現簡單的客戶端和服務端RPC客戶端服務端
- windows bilibili客戶端快取影片匯出Windows客戶端快取
- 獲取客戶端真實IP客戶端
- 詳解Nacos 配置中心客戶端配置快取動態更新的原始碼實現客戶端快取原始碼
- 客戶端骨架屏實現客戶端
- MySQL:MySQL客戶端快取結果導致OOMMySql客戶端快取OOM
- 如何利用sockserver模組程式設計實現客戶端併發Server程式設計客戶端
- .net 獲取客戶端真實ip客戶端
- java 獲取客戶端真實ipJava客戶端
- .Net 開源專案 FreeRedis 實現思路之 - Redis 6.0 客戶端快取技術Redis客戶端快取
- jQuery實現客戶端CheckAll功能jQuery客戶端
- 實踐篇 -- Redis客戶端快取在SpringBoot應用的探究Redis客戶端快取Spring Boot
- 使用傳統前端技術增強客戶端快取能力前端客戶端快取
- C#客戶端Redis伺服器的分散式快取C#客戶端Redis伺服器分散式快取
- 利用localstorage實現本地訊息快取快取
- golang實現tcp客戶端服務端程式GolangTCP客戶端服務端
- 獲取客戶端Mac地址客戶端Mac
- pomelo獲取客戶端IP客戶端
- Redis的Pub/Sub客戶端實現Redis客戶端
- 網頁SSH客戶端的實現網頁客戶端
- c#實現redis客戶端(一)C#Redis客戶端
- 伺服器獲取真實客戶端 IP伺服器客戶端
- 一種在客戶端利用js實現對資料校驗的方法客戶端JS
- laravel利用Redis來實現網站快取讀取LaravelRedis網站快取
- Android實現Thrift服務端與客戶端Android服務端客戶端
- Go 實現簡易的 Redis 客戶端GoRedis客戶端
- IM撤回訊息-iOS客戶端實現iOS客戶端
- FTP客戶端c程式碼功能實現FTP客戶端C程式
- Android-TCP客戶端的實現AndroidTCP客戶端
- Vue實現騰訊視訊Mac客戶端VueMac客戶端
- 實現客戶端加密,後臺解密薦客戶端加密解密
- 03. 實現客戶端應用程式客戶端
- c# 獲取客戶端IPC#客戶端
- oracle取客戶端網路卡地址Oracle客戶端