【轉】編寫高品質代碼改善C#程式的157個建議——建議57:實現ISerializable的子類型應負責父類的序列化

來源:互聯網
上載者:User

標籤:object   sts   copy   bin   圖片   min   cte   stat   files   

 

建議57:實現ISerializable的子類型應負責父類的序列化

我們將要實現的繼承自ISerializable的類型Employee有一個父類Person,假設Person沒有實現序列化,而現在子類Employee卻需要滿足序列化的情境。不過序列化器並沒有預設處理Person類型對象,這些事情只能由我們自己做。

以下是一個不妥的實現,序列化器只發現和處理了Employee中Salary欄位:

    class Program    {        static void Main()        {            Employee  liming = new Employee() { Name = "liming", Salary = 2000 };            BinarySerializer.SerializeToFile(liming, @"c:\", "person.txt");            Employee limingCopy = BinarySerializer.DeserializeFromFile<Employee>(@"c:\person.txt");            Console.WriteLine(string.Format("姓名:{0}", limingCopy.Name));            Console.WriteLine(string.Format("薪水:{0}", limingCopy.Salary));        }    }        public class Person    {        public string Name { get; set; }    }    [Serializable]    public class Employee : Person, ISerializable    {        public int Salary { get; set; }        public Employee()        {        }        protected Employee(SerializationInfo info, StreamingContext context)        {            Salary = info.GetInt32("Salary");        }        public override void GetObjectData(SerializationInfo info, StreamingContext context)        {            info.AddValue("Salary", Salary);        }    }    

序列化工具類:

    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;            }        }    }
View Code

輸出為:

姓名:
薪水:2000

看見,Name欄位並沒有正確處理。這需要我們修改類型Employee中受保護的構造方法GetObjectData方法,為它加入父類欄位的處理:

    [Serializable]    public class Employee : Person, ISerializable    {        public int Salary { get; set; }        public Employee()        {        }        protected Employee(SerializationInfo info, StreamingContext context)        {            Name = info.GetString("Name");            Salary = info.GetInt32("Salary");        }        public void GetObjectData(SerializationInfo info, StreamingContext context)        {            info.AddValue("Name", Name);            info.AddValue("Salary", Salary);        }    } 

修改後輸出:

姓名:liming
薪水:2000

上面的例子中Person類未被設定成支援序列化。現在,假設Person類已經實現了ISerializable介面,那麼這個問題處理起來會相對容易,在子類Employee中,我們只需要調用父類受保護的構造方法和GetObjectData方法就可以了。如下所示:

    [Serializable]    public class Person : ISerializable    {        public string Name { get; set; }        public Person()        {        }        protected Person(SerializationInfo info, StreamingContext context)        {            Name = info.GetString("Name");        }        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)        {            info.AddValue("Name", Name);        }    }    [Serializable]    public class Employee : Person, ISerializable    {        public int Salary { get; set; }        public Employee()        {        }        protected Employee(SerializationInfo info, StreamingContext context)            : base(info, context)        {            Salary = info.GetInt32("Salary");        }        public override void GetObjectData(SerializationInfo info, StreamingContext context)        {            base.GetObjectData(info, context);            info.AddValue("Salary", Salary);        }    }

 

 

 

 

轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技

【轉】編寫高品質代碼改善C#程式的157個建議——建議57:實現ISerializable的子類型應負責父類的序列化

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.