Serialization and deserialization in. Net, and. net deserialization
Serialization and deserialization are often heard and used, but some may not know :. net. net Frameword how to implement such a mechanism for us, here I also briefly talk about some of my understanding of serialization and deserialization.
1. What serialization and deserialization
Serialization is a process of converting an object into a byte stream, which can be easily stored in a disk file or database. Deserialization is a deserialization inverse process, that is, the process of transferring a byte back to the original object.
But why is serialization and deserialization required? This problem also involves the use of serialization and deserialization,
The main functions of serialization include:
1) Save the application state in a disk file or database, and restore the State when the application is run next time. For example, Asp.net uses serialization and deserialization) to save and restore session states.
3) A group of objects can be easily copied to the clipboard of Windows Forms, and pasted back to the same or another application.
Send an object from one application domain to another by value
If you serialize an object into a byte stream in the memory, you can use other technologies to process data, such as encrypting and compressing data.
Ii. simple use of serialization and deserialization
. Net Framework provides two serialization methods:
1) binary serialization
2) XML and SOAP serialization
Simple use of serialization and deserialization:
Using System; using System. IO; using System. runtime. serialization. formatters. binary; namespace Serializable {[Serializable] public class Person {public string personName; [NonSerialized] public string personHeight; private int personAge; public int PersonAge {get {return personAge ;} set {personAge = value ;}} public void Write () {Console. writeLine ("Person Name:" + personName); Console. writeLine ("Person Height:" + personHeight); Console. writeLine ("Person Age:" + personAge) ;}} class Program {static void Main (string [] args) {Person person Person = new person (); Person. personName = "Jerry"; person. personHeight = "175"; person. personAge = 22; Stream stream = Serialize (person); // reset stream for demonstration. position = 0; person = null; person = Deserialize (stream); person. write (); Console. read ();} private static MemoryStream Serialize (Person person) {MemoryStream stream = new MemoryStream (); // construct the binary serialization formatter BinaryFormatter binaryFormatter = new BinaryFormatter (); // tells the serializer to serialize the object to a stream in binaryFormatter. serialize (stream, person); return stream;} private static Person Deserialize (Stream stream) {BinaryFormatter binaryFormatter = new BinaryFormatter (); return (Person) binaryFormatter. deserialize (stream );}}}
It mainly calls the BinnaryFormatter class in the System. Runtime. Serialization. Formatters. Binary namespace for Serialization and deserialization. It calls the deserialization result:
It can be seen that all other Members marked with NonSerialized can be serialized. Note that this attribute can only be applied to a field of the type and will be inherited by the derived type.
The serialization and deserialization of SOAP and XML are similar to the above. You only need to change the formatter. I will not list it here.
Iii. Control serialization and deserialization
There are two methods to control serialization and deserialization:
Attributes such as OnSerializing, OnSerialized, OnDeserializing, OnDeserialized, NonSerialized, and OptionalField
Implement the System. Runtime. Serialization. ISerializable Interface
The first method controls the serialization and deserialization code:
Using System; using System. IO; using System. runtime. serialization; using System. runtime. serialization. formatters. binary; namespace ControlSerialization {[Serializable] public class Circle {private double radius; // radius [NonSerialized] public double area; // area public Circle (double inputradiu) {radius = inputradiu; area = Math. PI * radius;} [OnDeserialized] private void OnDeserialized (Streaming Context context) {area = Math. PI * radius;} public void Write () {Console. writeLine ("Radius is:" + radius); Console. writeLine ("Area is:" + area) ;}} class Program {static void Main (string [] args) {Circle c = new Circle (10 ); memoryStream stream = new MemoryStream (); BinaryFormatter formatter = new BinaryFormatter (); // serialize the object to the memory stream. Here you can use System. IO. an object of any type derived from the Stream abstract class. Here I use Memory Stream type. Formatter. serialize (stream, c); stream. position = 0; c = null; c = (Circle) formatter. deserialize (stream); c. write (); Console. read ();}}}
The running result is:
Note: If the OnDeserialized attribute is commented out, the value of the area field is 0, because the area field is not serialized into the stream.
In the object to be serialized above, the formatter only serializes the value of the radius field of the object. The value in the area field is not serialized, because the nonserializedattricle attribute has been applied to this field. Then, when we construct a Circle object using the code like Circle c = new Circle (10, area sets a value about 314.159. When this object is serialized, only the value of the radius field (10) is written into the stream, but when it is deserialized into a Circle object, the value of the "area" field is initialized to 0 instead of a value of about 314.159. To solve this problem, you can customize a method to apply the OnDeserializedAttribute attribute. At this time, the execution process is: every time an instance of the deserialization type is executed, the formatter checks whether a method that applies the attribute is defined in the type. If yes, the method is called, when this method is called, all serializable fields are correctly set. In addition to the ondeserializedattriingcustom attribute, the system. Runtime. Serialization namespace also defines the Custom Attributes OnSerializingAttribute, onserializedattriingand OnDeserializingAttribute.
Implement the ISerializable interface to control the serialization and deserialization code:
Using System; using System. IO; using System. runtime. serialization; using System. runtime. serialization. formatters. binary; using System. security. permissions; namespace ControlSerilization2 {[Serializable] public class MyObject: ISerializable {public int n1; public intn2; [NonSerialized] public String str; public MyObject () {} protected MyObject (SerializationInfo info, streamingContext context) {n1 = I Nfo. getInt32 ("I"); n2 = info. getInt32 ("j"); str = info. getString ("k");} [SecurityPermissionAttribute (SecurityAction. demand, SerializationFormatter = true)] public virtual void GetObjectData (SerializationInfo info, StreamingContext context) {info. addValue ("I", n1); info. addValue ("j", n2); info. addValue ("k", str);} public void Write () {Console. writeLine ("n1 is:" + n1); Console. writeLine ("n2 is: "+ N2); Console. writeLine ("str is:" + str) ;}} class Program {static void Main (string [] args) {MyObject obj = new MyObject (); obj. n1 = 2; obj. n2 = 3; obj. str = "Jeffy"; MemoryStream stream = new MemoryStream (); BinaryFormatter formatter = new BinaryFormatter (); // serialize the object to the memory stream. Here you can use System. IO. an object of any type derived from the Stream abstract class. Here I use the MemoryStream type. Formatter. serialize (stream, obj); stream. position = 0; obj = null; obj = (MyObject) formatter. deserialize (stream); obj. write (); Console. read ();}}}
Result:
The execution process is as follows: when the formatter serializes an object, it checks each object. If the ISerializable interface is implemented for an object type, the formatter ignores all the custom attributes, to construct a new System. runtime. serialization. serializationInfo object, which contains a set of values actually serialized for the object. After the SerializationInfo object is constructed and initialized, The formatter calls the GetObjectData method of the type and transmits a reference to the SerializationInfo object to it. The GetObjectData method determines the information needed to serialize the object, add the information to the SerializationInfo object and call the AddValue method to add each required data. After all necessary serialization information is added, it is returned to the formatter, the formatter then obtains all the values that have been added to the SerializationInfo object and serializes them to the stream. When deserialization is performed, the formatter extracts an object from the stream, memory will be allocated for the new object. At first, all fields of this object are set to 0 or null. Then, the formatter checks whether the ISerializable interface is implemented. If this interface exists, the formatter tries to call a special constructor. Its parameters are exactly the same as those of the GetObjectData method.
Iv. How to serialize and deserialize The formatter
From the above analysis, we can see that the formatter is mainly working for serialization and deserialization. However, the following section describes how the formatter serializes an object that applies the SerializableAttribute attribute.
1. The formatzer calls the GetSerializableMembers method of FormatterServices: public static MemberInfo [] GetSerializableMembers (Type type, StreamingContext context ); this method uses the public and private implementation fields of the launch type (except for the Fields marked with the NonSerializedAttributee attribute ). Method returns an array composed of MemberInfo objects. Each element corresponds to a serializable instance field.
2. The object is serialized. reflection. the static method GetObjectData: public static object [] GetObjectData (Object obj, MemberInfo [] members) that is passed to FormatterServices through an array of MemberInfo objects. This method returns an array of objects, each element identifies the value of a field in the serialized object.
3. The formatter writes the complete name of the Assembly ID and type to the stream.
4. The formatter then traverses the elements in the two arrays and writes the names and values of each member to the stream.
The next step is to explain how the formatter automatically deserializes an object that applies the SerializableAttribute attribute.
1. The formatter reads the Assembly ID and complete type name from the stream.
2. The formatzer calls the static method GetUninitializedObject: public static Object GetUninitializedObject (Type ttype) of FormatterServices. This method allocates memory for a new Object, but does not call the constructor for the Object. However, all fields of the object are initialized to 0 or null.
3. The formatter constructs and initializes a MemberInfo array and calls the GetSerializableMembers method of FormatterServices. This method returns a set of fields that are serialized and need to be deserialized.
4. The formatter creates and initializes an Object Array Based on the data contained in the stream.
5. Pass the reference to the newly assigned Object, MemberInfo array, and parallel Object array to the static method PopulateObjectMembers of FormatterServices:
Public static Object PopulateObjectMembers (Object obj, MemberInfo [] members, Object [] data); this method traverses the array and initializes each field to a corresponding value.
Note: part of how to serialize and deserialize objects in formatting is taken from CLR via C # (Third edition), which allows beginners to further understand what the formatter is doing during serialization and deserialization.
This article on serialization and deserialization is finally completed. I hope it will be helpful to my friends.
Articles you may be interested in:
- Asp.net xml serialization and deserialization
- Asp.net serialization and deserialization demonstration
- Jquery combines form elements in json format and asp.net deserialization
- JSON serialization and deserialization instructions in ASP. NET
- . Net for serialization and deserialization instance Parsing
- . Net serialization and deserialization instances