[WP7] Windows Phone 7 適用之 IsolatedStorage 輔助工具

  • 3810
  • 0
  • WP7
  • 2013-08-14

目前 WP7 開發者能夠用來存取 local 端資訊的唯一方法還是只能透過 IsolatedStorage。在 WP7 手機上, 此種 IsolatedStorage 的存放位置並不允許使用者以目錄瀏覽的... 當然, 有人會將資訊儲存在「雲端」, 如此就無需把資料存放在手持裝置裡面。但是我們可能要考慮到一種情況, 就是一旦這個手機並未連上網際網路時 (可能是因為無系統服務或為了省電因素而將連線關閉等等), 所有必須透過網路存取的資料將會完全消失。這時候, 我們又必須重新回頭思考將資訊存放在 local 端的必要性。既然如此, 我們還是非得熟悉 IsolatedStorage 不可...

目前 WP7 開發者能夠用來存取 local 端資訊的唯一方法還是只能透過 IsolatedStorage。在 WP7 手機上, 此種 IsolatedStorage 的存放位置並不允許使用者以目錄瀏覽的。相對的, 同樣名稱的機制在 PC 上則略有不同 (有興趣的人可以參考「運用 Isolated Storage 儲存不同使用層級的共用或臨時資料」一文)。

當然, 有人會將資訊儲存在「雲端」, 如此就無需把資料存放在手持裝置裡面。但是我們可能要考慮到一種情況, 就是一旦這個手機並未連上網際網路時 (可能是因為無系統服務或為了省電因素而將連線關閉等等), 所有必須透過網路存取的資料將會完全消失。這時候, 我們又必須重新回頭思考將資訊存放在 local 端的必要性。既然如此, 我們還是非得熟悉 IsolatedStorage 不可。

儲存和取用 IsolatedStorage 的方式非常簡單, 以下我將示範兩種方法。第一種是透過 IsolatedStorageSettings :

IsolatedStorageSettings iS= IsolatedStorageSettings.ApplicationSettings;
if (iS.Contains("MyKey"))
    string input = iS["MyKey"] as string;

第二種方法則是透過其檔案系統 :

string _storageFile = "MyData.XML";
string output;
string LastError;
try
{
    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream readStream = new IsolatedStorageFileStream(_storageFile, FileMode.Open, store))
    using (TextReader reader = new StreamReader(readStream))
        output = reader.ReadToEnd();
    if (string.IsNullOrEmpty(output))
        LastError = "GetData() failed. There is no data in the storage";
}
catch (IsolatedStorageException ex)
{
    LastError = string.Format("GetData() caused an exception. Error: {0}", ex.Message);
}

以上我只列出讀取部份的程式片段, 寫入的部份也同樣簡單, 請讀者自行研究。

接下來, 我把我的 IsolatedStorage Helper 類別拿出來貢獻給大家吧! 程式如下, 直接拷貝過去使用即可:

using System;
using System.Net;
using System.Collections.Generic;
using System.Xml.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;

namespace Johnny
{
    /// <summary>
    /// IsolatedStorage helper class
    /// </summary>
    /// <typeparam name="T">Specify the type that is to be used</typeparam>
    public class StorageHelper<T>
    {
        public string FileName;
        public string LastError;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="_fileName">The file name that is to be used</param>
        public StorageHelper(string fileName)
        {
            FileName = fileName;
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public StorageHelper() { }

        /// <summary>
        /// Read from the isolated storage
        /// </summary>
        /// <returns>A List object will be returned. If there's anything wrong, null will be returned.</returns>
        public List<T> Read()
        {
            List<T> output = new List<T>();
            try
            {
                using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
                using (IsolatedStorageFileStream file = storage.OpenFile(FileName, FileMode.OpenOrCreate))
                using (TextReader reader = new StreamReader(file))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(List<T>));
                    output.AddRange((List<T>)xs.Deserialize(reader));
                }
            }
            catch(Exception ex)
            {
                LastError = string.Format("StorageHelper.Read() failed. Error: {0}", ex.Message);
                output = null;
            }
            return output;
        }

        /// <summary>
        /// Write objects into the isolated storage in XML form
        /// </summary>
        /// <param name="input">The objects to be written</param>
        /// <returns>If the write action succeeded, true is returned, or else false.</returns>
        public bool Write(List<T> input)
        {
            try
            {
                IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
                using (IsolatedStorageFileStream file = isoStorage.OpenFile(FileName, FileMode.Create))
                using (TextWriter writer = new StreamWriter(file))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(List<T>));
                    xs.Serialize(writer, input);
                    return true;
                }
            }
            catch (Exception ex)
            {
                LastError = string.Format("StorageHelper.Read() failed. Error: {0}", ex.Message);
                return false;
            }
        }
    }
}

這個 Helper 是支援泛型的, 所以你可以拿你自己的自訂型別去用 (如果你的自訂型別中使用了 TimeSpan 型別, 那麼程式中的 XmlSerializer 可能會出問題 - 它轉過去可能轉不回來。除此之外, 大致上都不會出問題)。當你把你的自訂型別透過它存到 IsolatedStorage 之後, 它是儲存成 XML 檔案的型式。讀取回來之後會自動 Deserialize 成為正確的型別物件, 所以你可以無需自己撰寫 Serializer/Deserializer。

現在假設你有一個自訂型別 MyType :

public class MyType
{
   public int myId;
   public string myName;
   public int myAge;
}

要把一個 List<MyType> 物件寫進去 IsolatedStorage 的方法如下:

List<MyType> list = new List<MyType>;
list.Add(new MyType() { myId = 0, myName = "Johnny", myAge = 27 });
list.Add(new MyType() { myId = 1 myName = "Tony", myAge = 28 });
list.Add(new MyType() { myId = 2 myName = "Anita", myAge = 26 });
list.Add(new MyType() { myId = 3 myName = "Grace", myAge = 19 });
StorageHelper<MyType> sh = new StorageHelper<MyType>("MyData.XML");
if (sh.Write(list))
   // successful
else
   // failed

把它讀出來也很簡單:

StorageHelper<MyType> sh = new StorageHelper<MyType>("MyData.XML");
List<MyType> list = sh.Read();
if (list == null)
   // failed
else
   // successful

在以上程式中, 如果遇到執行失敗, 都可以從 sh.LastError 字串中取得失敗原因的記錄。


Dev 2Share @ 點部落