建議55:利用定制特性減少可序列化的字段
特性(attribute)可以聲明式地為代碼中的目標元素添加注釋。運行時可以通過查詢這些托管塊中的元數據信息,達到改變目標元素運行時行為的目的。System.Runtime.Serialization命名空間下,有4個這樣的特性:
利用這些特性,可以更加靈活地處理序列化和反序列化。例如,我們可以利用這一點,進一步減少某些可序列化的字段。
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個建議》陸敏技