SERIALIZATION concept
Serialization is a .NET a mechanism for implementing object persistence (PERSISTENT). It is a process that converts data in the object into a single element (usually stream). Its inverse process is Deserialization. The core concept of Serialization is to view all data of an object as a separate unit.
Generally speaking, in both cases, it is very necessary for Serialization: 1) When we want to be able to save the current state to the storage medium so that we can reduce the object in the future; 2) When we want the object from An application space (Application Domain) is passed to another application space. For example, the Windows Form program uses the Serialization mechanism to implement clipboard Copy & Paste.
.NET Framework supports two types of Serialization: SHALLOW Serialization and Deep Serialization.
The so-called Shallow Serialization is converted to byte streaming of the value of the read-write property of the object, and the data inside the object (data that is not exposed through the READ-WRITE property) is not converted. XMLSerializer and Web Services use this technology.
Deep Serialization is more thorough than Shallow Serialization because it copies the actual value stored in the object private variable to the byte stream. And Deep Serialization also uses Serialize entire Object Graph. That is, if your object holds references to other objects, or all of these objects will be Serialize. BINARYFORMATTER and SOAPFORMATTER and .NET Remoting use Deep Serialization technology, which are even limited to Losformatter to generate status data stored in the web form page.
This article will focus on Deep Serialization.
SERIALIZATION process
.NET Framework provides automatic Serialization mechanisms via REFLECTION. When an object is serialized, its class name, assembly, and all data members of the class instance will be written into the storage medium. The Serialization Engine maintains tracking of all objects that have been serialized to ensure that the same object reference is only serialized once.
Typically, a serialization process will be triggered by the SERIALIZE method of formatter (such as binaryformatter). The SERIALIZATION process of the object is performed in accordance with the following rules:
1. Detect to ensure that Formatter has a proxy selector (SURROGATE Selector). If there is, check if the proxy selector holds a given object type. If there is, iSerializable.GetObjectData is called.
2. If Formatter has no proxy selector, or the agent selector has no object type, check whether the object is tagged with the Serializable property. If not, the SerializationException is thrown.
3. If the object is marked as serializable, check if the object is implemented. If this interface is implemented, getObjectData is called.
4. If the object does not implement the iSerializable interface, use the default serialization policy to serialize the domain that is not tagged with the Nonserialized property. Make your Class to be serialized
Through the analysis of the serialization process on the serialization process, we can see that there are two ways to enable a Class to be serialized: 1) Simply mark this class as serializable; 2) implement the iSerializable interface for this class, and Class is marked as serializable.
1, mark the serializable attribute
The way to mark the serializable property is the basic method of implementing Serialization. Lift a simple example:
[Serializable]
Public Class Person
{
Public string name = NULL;
Public int Age = 0;
}
You can use binaryformatter to serialize the above Class:
Person Sam = New Person ();
Sam.name = "sam";
SAM.AGE = 24;
IFORMATTER FORMATTER = New BinaryFormatter ();
Street stream = new filestream ("Sam.dat",
FileMode.create, FileAccess.write, Fileshare.none;
Formatter.Serialize (stream, sam);
stream.close ();
It is so simple, what you have to do is create an instance of Stream and a Formatter, then call the Formatter's Serialize method. After binaryformatter serialize, the data can still come back by binaryformatter deserialize, the method is equally simple to serialize, here is not described here.
If you don't want to serialize all domains in the class, you can choose from the Nonserialized property. Such as:
[Serializable]
Public Class Person
{
Public string name = NULL;
[Nonserialized]
Public int Age = 0;
}
In this way, the AGE domain will not be serialized.
It should be noted that the serializable attribute cannot be inherited. That is to say, if you want Person's derived class to be able to be serialize, then this derived class must also be tagged by the Serializable. Otherwise, the serializationException exception will be obtained.
Similarly, all of the Person class references to other classes, the classes they are cited should be capable of being able to be serialize. Most of the Class in .NET Framework implements the iSerializable interface, but some Class is not implemented, such as ImageList. You can pass the MSDN Library to a class list that implements the iSerializable interface. Be careful when using Class of this interface.
2, implement the iSerializable interface
The function of the serializable property is very powerful, which makes Serialize and DeserialIze very simple. But everything is favorable, and the automatic serialization method implemented by serializable is sometimes not flexible enough. We can't fully control the behavior of Serialize and DeserialIze, and some of their behavior is important to us. So what method we can control the behavior of Serialize and DeserialIze? The answer is that you can implement the iSerializable interface. The iSerializable interface gives us a bigger free to control Serialize and Deserialize, but it will undoubtedly we will have to write more code L. Let's take a look at how to implement the iSerializAbe interface. The iSerializable interface is located in the System.Runtime.Serialization name space, as follows:
Public Inferface iSerializable
{
Void getObjectData (SerializationInfo Info,
StreamingContext context);
}
It has only one way to getObjectData. Therefore, like implementing other interfaces, we must implement this method. However, with other interfaces is that for DeSerialization, we must also implement a special constructor (I call this constructor "serialized constructor"), this constructor has the same parameter list as getObjectData. Since this constructor is specifically used for the REFLECTION mechanism when the .NET Framework is in DeserialIze, we usually declare it as protected or private mode. As follows: (Of course, if you only need serialize without deserialize, you can also do this special constructor)
[Serializable]
Public Class Person: iSerializable
{
Public string name = NULL;
Public int Age = 0;
Public Person ()
{
}
Protected Person (SerializationInfo Info, StreamingContext Context)
{
Name = info.getstring ("name");
AGE = Info.get32 ("age");
}
Void iSerializable.GetObjectData (SerializationInfo Info,
StreamingContext context)
{
Info.addvalue ("Name", Name);
Info.addValue ("Age", AGE;
}
}
By implementing the iSerializable interface, we have the opportunity to control the behavior of Serialize in iSerializable.GetObjectData, and control the behavior of DeserialIze in the Serialized Construction Function. This interface provides us very comprehensive and flexible, so that we can even play some tricks in these two methods. For example, we can get another object that is different types of the SERIALIZE object by changing info.fultTypename when Deserialize.
Unique
The typical environment used by Serialization is talked out in the previous area, which is an object store, process data transfer, and the like that involves the persistence of objects. But in fact, it can also be applied to many other places, the key is whether we can think of serialization, sometimes thinking is also terrible. For example, let's take a look at how to use Serialization [1] in the Clone method. If we want to implement Clone methods for the Person class, we usually write this:
[Serializable]
Public Class Person: iCloneable
{
Public string name = NULL;
Public int Age = 0;
Public Object Clone ()
{
Person Person = New Person ();
Person.name = name;
Person.age = age;
Return Person;
}
}
If we use the method of serialization, the Clone function will be written as the following:
Public Object Clone ()
{
MemoryStream Stream = new memorystream ();
BinaryFormatter Formatter = new binaryformatter ();
Formatter.Serialize (stream, this);
stream.position = 0;
Return Formatter.deSerialIze (stream);
}
From these two implementations, it doesn't seem to benefit from using Serialization to implement Clone methods. But imagine that if you face a complex class inheritance system, you need to implement a Clone method from the base class to derived class. Using the first actual method, you will have to write a clone method for each class, and this method will become less and less frequent as data members, and will cause errors due to changes in data members (I used to I have encountered several times, because the member variables have been added to the Class, and the Clone method does not update in time, causing the runtime error. Oh, this error is still difficult to debug). Now you see the benefits of using the Serialization implementation? Yes, we only need to declare the Clone method as Virtual in the base class, and use the serialization method, then ensure that the base class and derived class can be SERIALIZE, all the troubles are not all solved?
to sum up
In modern software projects, no matter what projects involve object persistence, .Net is no exception, whether it is Windows Form, ASP.NET, or Web Services, you need to handle object persistence. The SERIALIZATION is the solution given by .NET to address this issue.
references
· [1] Rockford Lhotka, "Object Serialization In Visual Basic .NET", MSDN Library. The use of Serialization in the Clone method is from this article.
· Piet Obermeyer and Jonathan Hawkins, "Object Serialization In The .NET Framework", MSDN Library.