Object serialization in. Net (from Microsoft)

Source: Internet
Author: User
Abstract: Why use serialization? The two most important reasons are: Saving the object state in the storage media so that you can re-create identical copies in the future; by value, the object from an application Program The domain is sent to another application domain. For example, serialization can be used to save session states in ASP. NET and copy objects to the clipboard of Windows Forms. It can also be used to remotely pass objects from one application domain to another by value. This article briefly introduces serialization used in Microsoft. NET.

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.

The serialization mechanism must be balanced between ease of use and flexibility in an object-oriented environment. As long as you have sufficient control capabilities for this process, it can be automatically implemented to a large extent. 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 describe the reliable serialization mechanism provided by the. NET Framework and focus on some important features that enable you to customize the serialization process as needed.

Persistent Storage

We often need to save the field value of the object to 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 complex when you need to trace the object hierarchy. Imagine writing a large business application containing a large number of objects. programmers have to writeCodeTo save the fields and attributes to the disk and restore them from the disk. Serialization provides a quick way to easily achieve this goal.

The Common Language Runtime (CLR) manages the distribution of objects in the memory. the. NET Framework uses reflection to provide an automatic serialization mechanism. After the object is serialized, the class name, assembly, and all data members of the class instance are written to the storage media. Objects usually use member variables to store references to other instances. After the class is serialized, the serialization engine tracks all serialized reference objects to ensure that the same object is not serialized multiple times .. The serialization architecture provided by the. NET 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 markedSerializable(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

The object is valid only in the application domain of the created object. Unless the object is fromMarshalbyrefobjectIs derived or markedSerializableOtherwise, any attempt to pass the object as a parameter or return it as a result will fail. If the object is markedSerializable, The object will be automatically serialized, transmitted from one application domain to another application domain, and then deserialized, in this way, an exact copy of the object is generated in the second application domain. This process is usually called value-based mail.

If the object is fromMarshalbyrefobjectIf the result is derived, the object reference, not the object itself, is passed from an application domain to another application domain. You can alsoMarshalbyrefobjectThe derived object is markedSerializable. This object is serialized and pre-configuredSurrogateselectorThe formatting program of will control the serialization process and replace allMarshalbyrefobjectThe derived object. If not configuredSurrogateselectorThe serialization architecture will follow the following standard serialization rules (see the serialization process steps ).

Basic serialization

To make a class serializable, the simplest method is to useSerializableAttribute 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 = 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 callSerializeMethod. The stream and the object instance to be serialized are provided to this call as parameters. All member variables (or even private variables) in the class will be serialized, but this is not explicitly reflected in this example. In this regard, binary serialization is different from the XML serialization program that only serializes public fields.

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 = new filestream ("myfile. bin ", filemode. open, fileaccess. read, fileshare. read); myobject OBJ = (myobject) formatter. deserialize (fromstream); stream. close (); // The following is the proof console. writeline ("N1: {0}", obj. n1); console. writeline ("N2: {0}", obj. n2); console. writeline ("str: {0}", obj. str );

TheBinaryformatterHighly Efficient, which can generate extremely compact byte streams. All objects serialized using this formatting program can also be deserialized using it. This formatting program is undoubtedly an ideal tool for deserializing objects that will be deserialized on the. NET platform. It should be noted that the constructor is not called when the object is deserialized. This constraint is added to deserialization for performance considerations. 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.

UseSoapformatter. All you have to do is replace the formatting program in the above CodeSoapformatter, AndSerializeAndDeserializeThe 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>

It must be noted that it cannot be inherited.SerializableAttribute. IfMyobjectIf 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, DescriptionMystuffThe 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 how to mark classes for serialization (because classes cannot be serialized after compilation), see the description below.Serialization rules).

Selective serialization

The class usually contains fields that should not be serialized. For example, assume that a class uses a member variable to store the thread ID. When this class is deserialized, the thread corresponding to the ID stored in the serialization class may no longer run, so serialization of this value is meaningless. You can useNonserializedAttribute 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

It can be implemented on objectsIserializableInterface 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 implementIserializableTo implementGetobjectdataMethod and a special constructor, which is used for deserializing objects. The following code example shows howMyobjectClass implementationIserializable.

[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 );}}

Called during serializationGetobjectdataYou need to fill inSerializationinfoObject. 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 addSerializationinfoMember variable. If the base object implementsIserializable, The derived class should callGetobjectdataMethod.

It must be emphasized thatIserializableTo add a class, you must also implementGetobjectdataAnd special constructors. IfGetobjectdata, The compiler will issue a warning. However, the constructor cannot be implemented forcibly, so no warning is given when the constructor is missing. If you try to deserialize a class without a constructor, an exception will occur. In terms of eliminating potential security and version control problems, the current design is superiorSetobjectdataMethod. For exampleSetobjectdataIf 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.SetobjectdataMethod. As you can imagine, if an object is performing some operations, but a malicious application callsSetobjectdataMethod will cause some potential troubles.

In the deserialization process, use the constructor provided for this purposeSerializationinfoPassed to the class. During object deserialization, any visibility constraints on constructors are ignored. Therefore, classes can be marked as public, protected, internal, or private. A good way is to mark the constructor as protect if the class is not encapsulated. If the class has been encapsulated, it should be marked as private. To restore the object state, you only need to use the name used during serialization, fromSerializationinfo. If the base class implementsIserializableThe base class constructor should be called so that the base object can restore its variables.

IfIserializableIf the new class contains any variable to be serialized, the constructor andGetobjectdataMethod. The following code snippet shows how to useMyobjectClass 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.

Objects are 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 the deserialization class is being implementedIdeserializationcallbackIs automatically called after the entire object chart is deserialized.OnserializationMethod. 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. It is very easy to retrieve keyword/value pairs during deserialization. However, the classes derived from the hash cannot be deserialized, therefore, some problems may occur when these objects are added to the return list. Therefore, we recommend that you do not call methods on the hash table.

Serialization procedure

Call on the formatting ProgramSerializeObject 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 callIserializable. getobjectdata.
    • If no proxy selector is available or you do not process this type, the system checks whether to useSerializableAttribute to mark the object. If not markedSerializationexception.
    • If the object has been correctly marked, check whether the object has been implemented.Iserializable. If it has been implemented, it will be called on the objectGetobjectdata.
    • If the object is not implementedSerializableWill use the default serialization policy, for all not markedNonserialized.
Version Control

The. NET Framework supports version control and side-by-side execution. If the class interfaces are consistent, all classes can work across versions. Serialization involves member variables rather than interfaces. Therefore, exercise caution when adding or deleting a member variable to a class to be serialized across versions. Especially for unimplementedIserializableClass. If the status of the current version changes (such as adding member variables, changing the variable type, or changing the variable name), it means that if existing objects of the same type are serialized using an earlier version, then they cannot be deserialized.

If the object state needs to change between different versions, the class author can have two options:

    • ImplementationIserializable. This allows you to precisely control the serialization and deserialization processes and correctly add and interpret future states during the deserialization process.
    • UseNonserializedAttribute 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 variableNonserializedTo 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 domainsMarshalbyrefobjectThis class is derived.
    • 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 markedNonserializedOr this class is not serialized at all.
    • Some data members contain sensitive information. In this case, we recommend that you implementIserializableAnd only serialize the required fields.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.