最近寫手機軟體,要使用到隔離儲存區(IsolatedStorage)來儲存與讀取檔案,但是一般的檔案儲存方式要自己定義格式來做檔案的儲存與讀取,於是乎想到用序列化的方式來儲存資料
而這邊我要介紹一個最簡單的方式-使用DataContract讓你快速儲存與讀取
前言
最近寫手機軟體,要使用到隔離儲存區(IsolatedStorage)來儲存與讀取檔案,但是一般的檔案儲存方式要自己定義格式來做檔案的儲存與讀取有點麻煩,於是乎想到用序列化的方式來儲存資料
而這邊我要介紹一個最簡單的方式-使用DataContract讓你快速儲存與讀取(WP7與WP8皆可)
對紀錄資料的類別做資料合約的定義
DataContract這個類別本身預設是把你有標記DataContract的類別與類別中屬性成員(標示DataMember)的資料序列化成XML格式的檔案,這邊用一個例子來見紹如何做資料合約
首先如果是WP7擇要要參考一下 System.Runtime.Serialize
並Include:
using System.Runtime.Serialization;
再來建一個我們需要記錄的資料類別,例如這邊做一個很簡單的學生類別
public class Student {
public Student(int id, string name, bool isGraduated) {
ID = id;
Name = name;
Graduated = isGraduated;
}
public int ID { get; set; }
public string Name { get; set; }
public bool Graduated;
}
再來加入標記,這邊我們對Student類別標示DataContract,告知此類別可以序列化,而裡面的屬性成員我們標示了DataMember,這些被標示DataMember的屬性或欄位會成為序列化為的資料
其中如果我們只是單純標註DataMember,則在序列化的檔案中,Element名稱會顯示類別中的屬性或欄位,如果你不想這麼做的話,則可以透過指定(Name=””) 的方式來定義Element的名稱
除此之外DataMember可以被標示給屬性或欄位,但是要是Public才可(網路上雖然說private field也可以,但是沒有試成功,不過還是建議用在public存取子),而屬性的部分要同時有get與set才可以
[DataContract]
public class Student {
public Student(int id, string name, bool isGraduated) {
ID = id;
Name = name;
Graduated = isGraduated;
}
[DataMember(Name="StudentID")]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public bool Graduated;
}
序列化至隔離儲存區中與反序列化
再來是IsolatedStorage序列化的部分
建構子時,先設定取得隔離儲存區資訊,以及先告知資料合約序列化類別,我們要處理類別型態
這邊我們介紹DataContractSerializer ,他繼承了XmlObjectSerializer,所以透過DataContractSerializer 會把資料序列化成XML格式的檔案
string fileName;
IsolatedStorageFile recordFile;
string recordTargetFolderName;
DataContractSerializer serializer; //對資料合約做序列化與反序列化處理的類別
// 建構函式
public MainPage()
{
InitializeComponent();
recordFile = IsolatedStorageFile.GetUserStoreForApplication();
fileName = "student.txt";
recordTargetFolderName = "StudentRecord";
serializer = new DataContractSerializer(typeof(Student)); //告知類別型態
}
序列化儲存
public void SaveData(Student saveData)
{
string TargetFileName = String.Format("{0}\\{1}",
recordTargetFolderName, fileName);
if (!recordFile.DirectoryExists(recordTargetFolderName))
recordFile.CreateDirectory(recordTargetFolderName);
try
{
using (var targetFile = recordFile.CreateFile(TargetFileName))
{
serializer.WriteObject(targetFile, saveData); //序列化
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
反序列化取得資料
public Student LoadData()
{
Student s = null;
string TargetFileName = String.Format("{0}\\{1}",
recordTargetFolderName, fileName);
try
{
if (recordFile.FileExists(TargetFileName))
{
using (var sourceStream = recordFile.OpenFile(TargetFileName, FileMode.Open))
{
s = (Student)serializer.ReadObject(sourceStream);//反序列化
}
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
return s;
}
結果畫面
儲存範例(由於筆電舊就沒有支援跑模擬器,所以只好用拍的)
而這是使用IsoStoreSpy觀看隔離存存區的檔案,其中綠色的線條就是我們在Student類別中定義 [DataMember(Name="StudentID")] 的部分,定義的名稱會顯示在Element上
讀檔畫面
如果有想要用序列化快速儲存與讀取檔案的人可以試試看唷!
參考資料
Windows Phone 7 Serialization: DataContract Serialization
C# DataContract Attribute for Private Fields?
文章中的敘述如有觀念不正確錯誤的部分,歡迎告知指正 謝謝 =)
另外要轉載請附上出處 感謝