Writing high-quality code to improve the C # program's 157 suggestions-recommendation 57: the sub-type implementing ISerializable should be responsible for serialization of the parent class,
Recommendation 57: the sub-type implementing ISerializable should be responsible for serialization of the parent class
The type of Employee that inherits from ISerializable has a parent class Person. Assume that the Person class does not implement serialization, but the current sub-class Employee needs to meet the serialization scenario. However, the serializer does not process objects of the Person type by default. We can only do these tasks by ourselves.
The following is an improper implementation. The serializer only discovers and processes the Salary field in the Employee:
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 ("Name: {0}", limingCopy. name); Console. writeLine (string. format ("Salary: {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 );}}
Serialization tool class:
Public class BinarySerializer {// Serialize the type to a string 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 () ;}}// serialize the type to public static void SerializeToFile (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 () ;}// Deserialize the string to 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; }}// Deserialize the object to 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
Output:
Name:
Salary: 2000
The Name field is not correctly processed. In this case, we need to modify the Protected Construction Method GetObjectData in the type of Employee to add the parent class field for processing:
[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); } }
Output after modification:
Name: liming
Salary: 2000
In the above example, the Person class is not set to support serialization. Now, if the Person class has implemented the ISerializable interface, the problem will be easily handled. In the subclass Employee, we only need to call the Protected Construction Method and GetObjectData method of the parent class. As follows:
[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); } }