Introduction
Serialization refers to the process of storing the status of the object instance to the storage media. In this process, first convert the Public and Private fields of the object and the name of the class (including the Assembly where the class is located) to the byte stream, and then write the byte stream into the data stream. When the object is deserialized, a copy identical to the original object will be created.
In
When implementing the serialization mechanism in an object-oriented environment, you must make some trade-offs between ease of use and flexibility. As long as you have sufficient control capabilities for this process, it can be automatically implemented to a large extent. Example
For example, simple binary serialization cannot meet the requirements, or, for specific reasons, determine the fields in the class to be serialized. The following sections will be discussed:
. Net
The reliable serialization mechanism provided by the framework focuses on some important features that enable you to customize the serialization process as needed.
Persistent Storage
We often need to preserve the field value of the object
Store the data in the disk and retrieve the data later. Although this can be done without serialization, this method is often cumbersome and error-prone, and will become more and more when you need to trace the object hierarchy
Complex. Imagine writing a large business application that contains a large number of objects. The programmer has to write code for each object to save the fields and attributes to the disk and restore these fields and
Attribute. Serialization provides a quick way to easily achieve this goal.
Common Language Runtime (CLR)
Manage the distribution of objects in the memory. net
The framework provides an automatic serialization mechanism by using reflection. After the object is serialized, the class name, assembly, and all data members of the class instance are written to the storage media. Objects are usually stored with member variables.
Instance reference. After the class is serialized, the serialization engine tracks all serialized reference objects to ensure that the same object is not serialized multiple times .. Net
The serialization architecture provided by the framework can automatically and correctly process object charts and circular references. The only requirement for object charts is that all objects referenced by objects being serialized must be marked
Ref = "tag-863-1.html"> serializable (see Basic serialization ). Otherwise, an exception occurs when the serialization program attempts to serialize unlabeled objects.
When deserializing A serialized class, the class is re-created and the values of all data members are automatically restored.
Send by value
Valid only for the application domain where the object is created. Unless the object is from
Export albyrefobject is derived or marked
Serializable. Otherwise, any attempt to pass the object as a parameter or return it as a result will fail. If the object is marked
Serializable, the object will be automatically serialized, transmitted from one application domain to another application domain, and then deserialized to generate this pair in the second application domain
An exact copy of the image. This process is usually called value-based mail.
If the object is from marshalbyrefobject
If the result is derived, the object reference, not the object itself, is passed from an application domain to another application domain. You can also
The object derived from marshalbyrefobject is marked
Serializable. This object is serialized and pre-configured
Surrogateselector
The formatting program of will control the serialization process and replace all
The object derived from marshalbyrefobject. If not configured
Surrogateselector, the serialization architecture will follow the following standard serialization rules (see the steps in the serialization process ).
Basic serialization
The simplest way to make a class serializable is to use serializable.
Attribute to mark it as follows:
**************************************** **************************************** ******
[Serializable]
Public class myobject {
Public int n1 = 0;
Public int n2 = 0;
Public String STR =
NULL;
}
**************************************** **************************************** ******
The following code snippet illustrates how to serialize an instance of this type into a file:
**************************************** **************************************** ******
Myobject OBJ = new myobject ();
OBJ. n1 = 1;
OBJ. n2 = 24;
OBJ. Str = "some strings ";
Iformatter formatter = new binaryformatter ();
Stream stream = new filestream ("myfile. bin", filemode. Create, fileaccess. Write, fileshare. None );
Formatter. serialize (stream, OBJ );
Stream. Close ();
**************************************** **************************************** ******
In this example, the binary formatting program is used for serialization. You only need to create an instance of the stream and formatting program to be used, and then call
Serialize
Method. The stream and the object instance to be serialized are provided to this call as parameters. All member variables (or even marked
Private
Will be serialized, but this is not explicitly reflected in this example. At this point, binary serialization is different from only serializing public fields.
XML serialization program.
It is also easy to restore an object to its previous state. First, create a formatter and a stream for reading, and then let the formatter deserialize the object. The following code snippet describes how to perform this operation.
**************************************** **************************************** ******
Iformatter formatter = new
Binaryformatter ();
Stream stream = new filestream ("myfile. bin", filemode. Open, fileaccess. Read, fileshare. Read );
Myobject OBJ = (myobject) formatter. deserialize (fromstream );
Stream. Close ();
// Output verification is shown below
Console. writeline ("N1: {0}", obj. N1 );
Console. writeline ("N2: {0}", obj. N2 );
Console. writeline ("str: {0}", obj. Str );
**************************************** **************************************** ******
Binaryformatter used above
Highly Efficient, which can generate extremely compact byte streams. All objects serialized using this formatting program can also be used for deserialization.
. Net
This formatting program is undoubtedly an ideal tool for deserializing objects on the platform. It should be noted that the constructor is not called when the object is deserialized. This constraint is added to deserialization because of performance.
. However, this violates some runtime conventions used by object writers. Therefore, when marking objects as serializable, developers should ensure that this special convention is taken into account.
----------------------------------
Portable soapformatter
Use
Soapformatter. All you have to do is replace the formatting program in the above Code
Soapformatter, while serialize and deserialize
The call remains unchanged. For the example used above, the formatter will generate the following results.
<SOAP-ENV: Envelope
Xmlns: xsi = http://www.w3.org/2001/XMLSchema-instance
Xmlns: XSD = "http://www.w3.org/2001/XMLSchema"
Xmlns: Soap-
ENC = http://schemas.xmlsoap.org/soap/encoding/
Xmlns: Soap-
ENV = http://schemas.xmlsoap.org/soap/envelope/
SOAP-ENV: encodingstyle =
Http://schemas.microsoft.com/soap/encoding/clr/1.0
Http://schemas.xmlsoap.org/soap/encoding"
Xmlns: A1 = "http://schemas.microsoft.com/clr/assem/ToFile">
SOAP-ENV: Body>
<A1: myobject
Id = "ref-1">
<N1> 1 </N1>
<N2> 24 </N2>
<Str
Id = "ref-3"> some strings </STR>
</A1: myobject>
SOAP-ENV: Body>
SOAP-ENV: envelope>
Note that the serializable attribute cannot be inherited. If
If a new class is derived, the new class must also be marked with this attribute; otherwise, the class cannot be serialized. For example, if you try to serialize the following class instances,
Serializationexception, indicating mystuff
The type is not marked as serializable.
Public class mystuff: myobject
{
Public int N3;
}
The serialization attribute is very convenient, but it has some restrictions described above. For more information about when to mark classes for serialization (because classes cannot be serialized after compilation), see the description (see serialization rules below ).
----------------------------------
Selective serialization
The class usually contains fields that should not be serialized. For example, assume that a class uses a member variable to store threads.
Id. Id stored when this class is deserialized and serialized
The corresponding thread may no longer run, so serialization of this value is meaningless. You can use
Nonserialized
Attribute tag member variables to prevent them from being serialized, as shown below:
[Serializable]
Public class myobject
{
Public int N1;
[Nonserialized] public int
N2;
Public String STR;
}
----------------------------------
Custom serialization
You can implement iserializable on the object.
Interface to customize the serialization process. This function is especially useful when the value of the member variable becomes invalid after deserialization, but you need to provide the value for the variable to recreate the complete state of the object. To implement
Iserializable. getobjectdata must be implemented.
Method and a special constructor, which is used for deserializing objects. The following code example shows how
Implement iserializable in the myobject class.
[Serializable]
Public class myobject: iserializable
{
Public int N1;
Public int N2;
Public String STR;
Public
Myobject ()
{
}
Protected
Myobject (serializationinfo info, streamingcontext context)
{
N1 = info. getint32 ("I ");
N2 = info. getint32 ("J ");
STR =
Info. getstring ("K ");
}
Public
Virtual void getobjectdata (serializationinfo info,
Streamingcontext context)
{
Info. addvalue ("I", N1 );
Info. addvalue ("J", N2 );
Info. addvalue ("K", STR );
}
}
When getobjectdata is called during serialization, you need to fill in
Serializationinfo
Object. You only need to add the variable to be serialized in the form of name/value pairs. The name can be any text. As long as the serialized data is sufficient to restore the object during the deserialization process, you can freely choose to add
The member variable of serializationinfo. If the base object implements
Iserializable, the derived class should call the getobjectdata of its base object
Method.
It should be emphasized that the iserializable
To add a class, you must also implement getobjectdata
And special constructors. If
Getobjectdata, the compiler will issue a warning. However, the constructor cannot be implemented forcibly, so no warning is given when the constructor is missing. If no constructor is available
Serialization of A Class causes an exception. In terms of eliminating potential security and version control problems, the current design is superior
Setobjectdata method. For example, if you set setobjectdata
If a method is defined as a part of an interface, the method must be a public method, so that you have to write code to prevent multiple calls.
Setobjectdata
Method. As you can imagine, if an object is performing some operations, but a malicious application calls
The setobjectdata method may cause some potential troubles.
In the deserialization process, use the constructor provided for this purpose
Serializationinfo
Passed to the class. When the object is deserialized, any visibility constraints on the constructor will be ignored. Therefore, you can mark the class
Public, protected, internal, or
Private. A good way is to mark the constructor
Protect. If the class has been encapsulated, it should be marked
Private. To restore the object state, you only need to use the name used during serialization, from
The value of the variable in serializationinfo. If the base class implements
Iserializable, you should call the constructors of the base class so that the base object can restore its variables.
If the iserializable
If the new class contains any variable to be serialized, the constructor and
Getobjectdata method. The following code snippet shows how to use the myobject
Class to complete this operation.
[Serializable]
Public class objecttwo: myobject
{
Public int num;
Public
Objecttwo (): Base ()
{
}
Protected
Objecttwo (serializationinfo Si, streamingcontext context ):
Base (Si, context)
{
Num =
Si. getint32 ("num ");
}
Public
Override void getobjectdata (serializationinfo Si,
Streamingcontext context)
{
Base. getobjectdata (Si, context );
Si. addvalue ("num", num );
}
}
Remember to call the base class in the deserialization constructor. Otherwise, the constructor on the base class will never be called, and the complete object cannot be constructed after deserialization.
Pair
Such as being completely re-built, but calling methods in the deserialization process may bring adverse side effects, because the called methods may reference object references that are not deserialized at the call fashion. If reverse order is being performed
Column-based class implementation
Ideserializationcallback is automatically called after the entire object chart is deserialized.
Onserialization
Method. All referenced sub-objects are completely restored. Some classes do not use the above event listeners, so it is difficult to deserialize them. The hash is a typical example. Key to retrieval during deserialization
Word/value pairs are very easy. However, because classes derived from the hash list cannot be deserialized, some problems may occur when these objects are added to the hash list. Therefore, we recommend that you do not call
Method.
Serialization procedure
Call serialize on the formatting Program
Object serialization is performed according to the following rules:
Check whether the formatting program has a proxy selector. If yes, check whether the proxy Selector Processes objects of the specified type. If the Selector Processes this object type, it will call
Iserializable. getobjectdata.
If there is no proxy selector or there is but this type is not processed, the system checks whether serializable is used.
Attribute to mark the object. If not marked
Serializationexception.
If the object has been correctly marked, check whether the object has been implemented.
Iserializable. If implemented, getobjectdata is called on the object.
If the object does not implement serializable, the default serialization policy is used for all
All nonserialized fields are serialized.
Version Control
. Net
The Framework supports version control and side-by-side execution. If the class interfaces are consistent, all classes can work across versions. Because serialization involves member variables rather than interfaces
Exercise caution when adding or deleting member variables. Especially for unimplemented
Iserializable
Class. If the status of the current version changes (for example, adding a member variable, changing the variable type, or changing the variable name), it means that if an existing object of the same type uses an earlier version for sorting
If they are column-based, they cannot be deserialized successfully.
If the object state needs to change between different versions, the class author can have two options:
Implementation
Iserializable. This allows you to precisely control the serialization and deserialization processes and correctly add and interpret future states during the deserialization process.
Use nonserialized
Attribute flag is not an important member variable. This option can be used only when the expected class changes between different versions. For example, you can mark a new variable
Nonserialized to ensure compatibility with earlier versions.
Serialization rules
Since classes cannot be serialized after compilation, serialization should be considered when designing new classes. The question to consider is: Must this class be sent across application domains? Do you want to remotely use this class? How will users use this class?
Maybe they will generate a new class to be serialized from my class. As long as this possibility exists, classes should be marked as serializable. It is recommended to mark all classes as serializable except in the following cases:
All classes will never span application domains. If a class does not require serialization but must span application domains
Marshalbyrefobject derives this class.
Class storage only applies to the special pointers of its current instance. For example, if a class contains uncontrolled memory or file handles, make sure that these fields are marked
Nonserialized or do not serialize this class at all.
Some data members contain sensitive information. In this case, we recommend that you implement iserializable
And only serialize the required fields.
----------------------------------
Note: You need to introduce the namespace:
Using system. runtime. serialization;
Using system. runtime. serialization. formatters. Binary; // binary formatter = new binaryformatter (); required
Q: Why does the system prompt "not marked as serializable "?
Solution: add the following mark before the class: [serializable]
[Serializable] <br/> public class proclass <br/>{< br/> Public int A; <br/> Public int B; <br/>}
Refer:
(1) What does not mark as serializable? Class serialization [serializable]
Http://blog.sina.com.cn/s/blog_4a808e610100ajbm.html
(2) implement with iformatter> storage container (function: Save and read games ).
Http://blog.csdn.net/chengking/archive/2006/01/06/510418.aspx
Reference 2 provides examples of serialization of various variables, and how to read the serialized content separately in a text: sequential de-reading and de-serialization.
Public void save (form2 form2) <br/> {<br/> // ****** serialize arrays, variables, and classes in form2 ******** // <br/> iformatter formatter = new binaryformatter (); // define the class, mainly using two methods in this class to implement the function <br/> stream = new filestream (this. savefilename, filemode. create, fileaccess. write, fileshare. none); </P> <p> // serialize the pictureboxstatus array in form2 <br/> formatter. serialize (stream, form2.pictureboxsstatus); <br/> formatter. serialize (stream, form2.battle); <br/> formatter. serialize (stream, form2.soldiers); <br/> formatter. serialize (stream, form2.temppoint); <br/> formatter. serialize (stream, form2.letdown); <br/> formatter. serialize (stream, form2.signright); <br/> formatter. serialize (stream, form2.starttime); </P> <p> stream. close (); <br/>}< br/> Public void read (ref form2 form2) <br/>{< br/> iformatter formatter = new binaryformatter (); <br/> stream = new filestream (this. openfilename, filemode. open, fileaccess. read, fileshare. read); </P> <p> // form2 A = new form2 (); <br/> form2 A = form2; </P> <p> // deserialize the pictureboxstatus array in form2 <br/>. pictureboxsstatus = (bool []) formatter. deserialize (Stream); </P> <p>. battle = (string) formatter. deserialize (Stream); <br/>. soldiers = (string []) formatter. deserialize (Stream); <br/>. temppoint = (point []) formatter. deserialize (Stream); <br/>. letdown = (bool) formatter. deserialize (Stream); <br/>. signright = (INT) formatter. deserialize (Stream); <br/>. starttime = (datetime) formatter. deserialize (Stream); </P> <p> stream. close (); <br/>}