【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4289字,纯文字阅读大概需要7分钟。
内容图文
建议56:使用继承ISerializable接口更灵活地控制序列化过程
接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttribute、OnDeserializingAttribute、OnSerializedAttribute、OnSerializingAttribute、NoSerializable等特性不能完全满足自定义序列化的要求,那就需要继承ISerializable了。
以下是格式化器的工作流程:如果格式化器在序列化一个对象的时候,发现对象继承了ISerializable接口,那它就会忽略掉类型所有的序列化特性,转而调用类型的GetObjectData方法来构造一个SerializationInfo对象,方法内部负责向这个对象添加所有需要序列化的字段(“添加”这个词可能不太恰当,因为我们在添加前可以随意处置这个字段)。以建议55中的例子为例,如果要为ChineseName构造对应的值,在类继承ISerializable接口的情况下,应该这样去实现:
class Program { static void Main() { Person liming = new Person() { FirstName = "Ming", LastName = "Li" }; BinarySerializer.SerializeToFile(liming, @"c:\", "person.txt"); Person p = BinarySerializer.DeserializeFromFile<Person>(@"c:\person.txt"); Console.WriteLine(p.FirstName); Console.WriteLine(p.LastName); Console.WriteLine(p.ChineseName); } } [Serializable] publicclass Person : ISerializable { publicstring FirstName; publicstring LastName; publicstring ChineseName; public Person() { } protected Person(SerializationInfo info, StreamingContext context) { FirstName = info.GetString("FirstName"); LastName = info.GetString("LastName"); ChineseName = string.Format("{0} {1}", LastName, FirstName); } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("FirstName", FirstName); info.AddValue("LastName", LastName); } }
序列化工具类:
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()); } } //将类型序列化为文件publicstaticvoid 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(); } } //将字符串反序列化为类型publicstatic 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; } } //将文件反序列化为类型publicstatic 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; } } }
我们在方法GetObjectData中处理序列化,然后在一个带参数的构造方法中处理反序列化。虽然在接口中没有地方指出需要这样一个构造器,但这确实是需要的,除非我们序列化后不再打算把它反序列化回来。
这个例子不能表现出ISerializable接口比Serializable特性的优势,见下面的例子:
将Person序列化,然后在反序列化中将其变为另一个对象:PersonAnother类型对象。要实现这个功能,需要Person和PersonAnother都实现ISerializable接口,原来其实很简单,就是在Person类的GetObjectData方法中处理序列化,在PersonAnother的受保护构造方法中反序列化。
class Program { static void Main() { Person liming = new Person() { FirstName = "Ming", LastName = "Li" }; BinarySerializer.SerializeToFile(liming, @"c:\", "person.txt"); PersonAnother p = BinarySerializer.DeserializeFromFile<PersonAnother>(@"c:\person.txt"); Console.WriteLine(p.Name); } } [Serializable] class PersonAnother : ISerializable { publicstring Name { get; set; } protected PersonAnother(SerializationInfo info, StreamingContext context) { Name = info.GetString("Name"); } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { } } [Serializable] publicclass Person : ISerializable { publicstring FirstName; publicstring LastName; publicstring ChineseName; public Person() { } protected Person(SerializationInfo info, StreamingContext context) { } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.SetType(typeof(PersonAnother)); info.AddValue("Name", string.Format("{0} {1}", LastName, FirstName)); } }
在Person类型的GetObjectData方法中,有句代码非常重要:
info.SetType(typeof(PersonAnother));
它负责告诉序列化器:我要被反序列化为PersonAnother。而类型PersonAnother则很简单,它甚至都不需要知道谁会被反序列化成它,它不需要做任何特殊处理。
ISerializable接口这个特性很重要,如果运用得当,在版本升级中,它能处理类型因为字段变化而带来的问题。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
原文:http://www.cnblogs.com/farmer-y/p/7991961.html
内容总结
以上是互联网集市为您收集整理的【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程全部内容,希望文章能够帮你解决【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。