编写高质量代码改善C#程序的157个建议——建议57:实现ISerializable的子类型应负责父类的序列化

王朝学院·作者佚名  2016-08-28
窄屏简体版  字體: 小  |  中  |  大  |  超大  

建议57:实现ISerializable的子类型应负责父类的序列化

我们将要实现的继承自ISerializable的类型Employee有一个父类Person,假设Person没有实现序列化,而现在子类Employee却需要满足序列化的场景。不过序列化器并没有默认处理Person类型对象,这些事情只能由我们自己做。

以下是一个不妥的实现,序列化器只发现和处理了Employee中Salary字段:

classPRogram

{staticvoidMain()

{

Employee liming=newEmployee() { 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));

}

}publicclassPerson

{publicstringName {get;set; }

}

[Serializable]publicclassEmployee : Person, ISerializable

{publicintSalary {get;set; }publicEmployee()

{

}protectedEmployee(SerializationInfo info, StreamingContext context)

{

Salary= info.GetInt32("Salary");

}publicoverridevoidGetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("Salary", Salary);

}

}

序列化工具类:

[flash=500,400]http://s1.knowsky.com/20160211/5ovxhdqzbzb49.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/mlnlqzwmkif49.gif[/flash]publicclassBinarySerializer

{//将类型序列化为字符串publicstaticstringSerialize<T>(T t)

{using(MemoryStream stream =newMemoryStream())

{

BinaryFormatter formatter=newBinaryFormatter();

formatter.Serialize(stream, t);returnSystem.Text.Encoding.UTF8.GetString(stream.ToArray());

}

}//将类型序列化为文件publicstaticvoidSerializeToFile<T>(T t,stringpath,stringfullName)

{if(!Directory.Exists(path))

{

Directory.CreateDirectory(path);

}stringfullPath =Path.Combine(path, fullName);using(FileStream stream =newFileStream(fullPath, FileMode.OpenOrCreate))

{

BinaryFormatter formatter=newBinaryFormatter();

formatter.Serialize(stream, t);

stream.Flush();

}

}//将字符串反序列化为类型publicstaticTResult Deserialize<TResult>(strings)whereTResult :class{byte[] bs =System.Text.Encoding.UTF8.GetBytes(s);using(MemoryStream stream =newMemoryStream(bs))

{

BinaryFormatter formatter=newBinaryFormatter();returnformatter.Deserialize(stream)asTResult;

}

}//将文件反序列化为类型publicstaticTResult DeserializeFromFile<TResult>(stringpath)whereTResult :class{using(FileStream stream =newFileStream(path, FileMode.Open))

{

BinaryFormatter formatter=newBinaryFormatter();returnformatter.Deserialize(stream)asTResult;

}

}

}

View Code

输出为:

姓名:

薪水:2000

看见,Name字段并没有正确处理。这需要我们修改类型Employee中受保护的构造方法GetObjectData方法,为它加入父类字段的处理:

[Serializable]publicclassEmployee : Person, ISerializable

{publicintSalary {get;set; }publicEmployee()

{

}protectedEmployee(SerializationInfo info, StreamingContext context)

{

Name= info.GetString("Name");

Salary= info.GetInt32("Salary");

}publicvoidGetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("Name", Name);

info.AddValue("Salary", Salary);

}

}

修改后输出:

姓名:liming

薪水:2000

上面的例子中Person类未被设置成支持序列化。现在,假设Person类已经实现了ISerializable接口,那么这个问题处理起来会相对容易,在子类Employee中,我们只需要调用父类受保护的构造方法和GetObjectData方法就可以了。如下所示:

[Serializable]publicclassPerson : ISerializable

{publicstringName {get;set; }publicPerson()

{

}protectedPerson(SerializationInfo info, StreamingContext context)

{

Name= info.GetString("Name");

}publicvirtualvoidGetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("Name", Name);

}

}

[Serializable]publicclassEmployee : Person, ISerializable

{publicintSalary {get;set; }publicEmployee()

{

}protectedEmployee(SerializationInfo info, StreamingContext context)

:base(info, context)

{

Salary= info.GetInt32("Salary");

}publicoverridevoidGetObjectData(SerializationInfo info, StreamingContext context)

{base.GetObjectData(info, context);

info.AddValue("Salary", Salary);

}

}

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航