標籤:
建議55:利用定製特性減少可序列化的欄位
特性(attribute)可以聲明式地為代碼中的目標元素添加註釋。運行時可以通過查詢這些託管塊中的中繼資料資訊,達到改變目標元素運行時行為的目的。System.Runtime.Serialization命名空間下,有4個這樣的特性:
- OnDeserializedAttribute,當它應用於某方法時,會指定在對象還原序列化後立即調用此方法。
- OnDeserializingAttribute,當他應用於某方法是,會指定在還原序列化對象時調用此方法。
- OnSerializedAttribute,當它應用於某方法時,會指定在對象序列化後立即調用此方法。
- OnSerializingAttribute,當他應用於某方法是,會指定在序列化對象時調用此方法。
利用這些特性,可以更加靈活地處理序列化和還原序列化。例如,我們可以利用這一點,進一步減少某些可序列化的欄位。
Person類由ChineseName、FirstName、LastName欄位組成:
[Serializable] class Person { public string FirstName; public string LastName; public string ChineseName; }
我們知道,ChineseName實際可以有FirstName和LastName推斷出,所以這意味著ChineseName不需要被序列化。這時候,我們就可以利用特性,提供一個方法在序列化完成後計算ChineseName的值:
class Program { static void Main() { Person liming = new Person() { FirstName = "Ming", LastName = "Li", ChineseName = "Li Ming" }; BinarySerializer.SerializeToFile(liming, @"c:\", "Person.txt"); Person person = BinarySerializer.DeserializeFromFile<Person>(@"c:\Person.txt"); Console.WriteLine(person.ChineseName); } } [Serializable] class Person { public string FirstName; public string LastName; [NonSerialized] public string ChineseName; [OnDeserializedAttribute] void OnSerialized(StreamingContext context) { ChineseName = string.Format("{0} {1}", LastName, FirstName); } }
序列化工具類:
public class BinarySerializer { //將類型序列化為字串 public static string Serialize<T>(T t) { using (MemoryStream stream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, t); return System.Text.Encoding.UTF8.GetString(stream.ToArray()); } } //將類型序列化為檔案 public static void SerializeToFile<T>(T t, string path, string fullName) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string fullPath = Path.Combine(path, fullName); using (FileStream stream = new FileStream(fullPath, FileMode.OpenOrCreate)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, t); stream.Flush(); } } //將字串還原序列化為類型 public static TResult Deserialize<TResult>(string s) where TResult : class { byte[] bs = System.Text.Encoding.UTF8.GetBytes(s); using (MemoryStream stream = new MemoryStream(bs)) { BinaryFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(stream) as TResult; } } //將檔案還原序列化為類型 public static TResult DeserializeFromFile<TResult>(string path) where TResult : class { using (FileStream stream = new FileStream(path, FileMode.Open)) { BinaryFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(stream) as TResult; } } }
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
編寫高品質代碼改善C#程式的157個建議——建議55:利用定製特性減少可序列化的欄位