Serialization mechanism under the. NET Framework

Source: Internet
Author: User

When writing an application, programmers often need to store some data of the program in the memory, and then write it into a file or transmit it to another computer on the network for communication. This process of converting program data into a stored and transmitted format is called "serialization", and its inverse process can be called "deserialization ).

. Net Framework has excellent support for the serialization mechanism. It provides two namespaces: system. runtime. serialization and system. runtime. serialization. formatters to complete most of the functions of the serialization mechanism. Serialization can be applied to store the results data generated by the program to the file system, but it is mainly applied to the implementation of. Net remoting and Web services.

The serialization mechanism is implemented by formatter. It is a Class Object inherited from system. runtime. serialization. iformatter. The formatter converts program data to a format that can be stored and transmitted, and also converts the data back .. The. NET Framework provides two types of formatters for programmers. One is usually applicable to desktop applications, and the other is system. runtime. serialization. formatters. binary. the binaryformatter class, and the other is more important. net remoting and XML Web Services, one of which is system. runtime. serialization. formatters. soap. object of the soapformatter class. From the perspective of their names, we may call them binary formatters and XML formatters respectively.

This article will start with the two formatters, first introduce how to use them to implement serialization and deserialization, and then compare the differences between the two formatters. Next, I will introduce some requirements on Object Types for serialization, and introduce two different serialization Methods: Basic serialization) and custom serialization ). Finally, I will introduce you to an instance program to deepen your understanding of the serialization mechanism.

1. Binary formatter vs XML formatter ):

Next, I will first introduce two different formatters, how to use them to implement the serialization mechanism and deserialization mechanism. Please refer to the following code:

# Region binary serializers
Public static system. Io. memorystream serializebinary (Object Request ){
System. runtime. serialization. formatters. Binary. binaryformatter serializer =
New system. runtime. serialization. formatters. Binary. binaryformatter ();
System. Io. memorystream memstream = new system. Io. memorystream ();
Serializer. serialize (memstream, request );
Return memstream;
}

Public static object deserializebinary (system. Io. memorystream memstream ){
Memstream. Position = 0;
System. runtime. serialization. formatters. Binary. binaryformatter deserializer =
New system. runtime. serialization. formatters. Binary. binaryformatter ();
Object newobj = deserializer. deserialize (memstream );
Memstream. Close ();
Return newobj;
}
# Endregion

# Region XML serializers
Public static system. Io. memorystream serializesoap (Object Request ){
System. runtime. serialization. formatters. Soap. soapformatter serializer =
New system. runtime. serialization. formatters. Soap. soapformatter ();
System. Io. memorystream memstream = new system. Io. memorystream ();
Serializer. serialize (memstream, request );
Return memstream;
}

Public static object deserializesoap (system. Io. memorystream memstream ){
Object SR;
System. runtime. serialization. formatters. Soap. soapformatter deserializer =
New system. runtime. serialization. formatters. Soap. soapformatter ();
Memstream. Position = 0;
Sr = deserializer. deserialize (memstream );
Memstream. Close ();
Return SR;
}
# Endregion
 

From the above code, we can find that no matter which formatter is used, the basic process is the same, and it is very easy to implement. The only difference is that the type of the formatter is different. However, in practical applications, the binary formatter is often used in general desktop programs and network communication programs, while the XML formatter inherits the advantages of XML technology, and most of them are used. net remoting and XML Web Services. Next we will analyze the advantages of the two formats.

Advantages of binary serialization:

1. All class members (including read-only members) can be serialized;

2. excellent performance.

Advantages of XML serialization:

1. Good interoperability;

2. Strict binary dependency is not required;

3. High readability.

By analyzing the code above, we know whether to select the binary serialization method or the XML serialization method is just to select different formatters. You can select a formatter to complete serialization and deserialization based on your actual needs. At the same time, note that the serialization and deserialization functions in the Code are only different in calling the two core functions serialize () and deserialize (), that is, their parameters are different. Therefore, the above Code has completed some of the most basic but important functions, you can apply them to your program, or expand it to meet the specific needs of the program.

Ii. Requirements of the serialization mechanism for classes:

If you want to serialize an object, you must mark its type as [serializable ()]. This operation is implemented through the serializableattribute. Applying the serializableattribute attribute to a data type indicates that instances of the data type can be serialized. If the serializableattribute is not applied to any type of the serialized object graph, the Common Language Runtime Library will cause serializationexception. By default, all public and private Fields marked by serializableattribute in the type are serialized, unless this type implements the iserializable interface to override the serialization process (by implementing this interface, we can implement the "Custom serialization" described later "). The default serialization process will exclude Fields marked with the nonserializedattribute attribute, that is, you can mark this type as [nonserialized ()] to indicate that it cannot be serialized. If a field of the serializable type contains pointers, handles, or other data structures for a specific environment, and cannot be reconstructed in a meaningful way in different environments, it is better to apply the nonserializedattribute attribute to this field. For more information about serialization, see related content in the system. runtime. serialization namespace.

The following example shows how to correctly use the serializableattribute and nonserializedattribute attribute. This program uses the XML formatter, but it also provides the binary formatter as a reference (the program uses the "//" annotation), and the implementation result is the same. The function implemented by this program is to display different screen print results before and after serialization and deserialization because the test object contains the [nonserialized ()] field. The Code is as follows:

Using system;
Using system. IO;
Using system. runtime. serialization;
Using system. runtime. serialization. formatters. Soap;
// Using system. runtime. serialization. formatters. Binary;

Public class test {
Public static void main (){
// Create a new test object
Testsimpleobject OBJ = new testsimpleobject ();

Console. writeline ("before serialization the object contains :");
OBJ. Print ();

// Create a file "data. xml" and serialize the object and store it in it
Stream stream = file. Open ("data. xml", filemode. Create );
Soapformatter formatter = new soapformatter ();
// Binaryformatter formatter = new binaryformatter ();

Formatter. serialize (stream, OBJ );
Stream. Close ();
  
// Empty the object
OBJ = NULL;

// Open the file "data. xml" and deserialize it to get the object
Stream = file. Open ("data. xml", filemode. Open );
Formatter = new soapformatter ();
// Formatter = new binaryformatter ();

OBJ = (testsimpleobject) formatter. deserialize (Stream );
Stream. Close ();

Console. writeline ("");
Console. writeline ("after deserialization the object contains :");
OBJ. Print ();
}
}

// A class of the test object to be serialized
[Serializable ()]
Public class testsimpleobject {
Public int member1;
Public String member2;
Public String member3;
Public double member4;

// Mark this field as not serializable
[Nonserialized ()] Public String member5;

Public testsimpleobject (){
Member1 = 11;
Member2 = "hello ";
Member3 = "hello ";
Member4 = 3.14159265;
Member5 = "Hello world! ";
}

Public void print (){
Console. writeline ("member1 = '{0}'", member1 );
Console. writeline ("member2 = '{0}'", member2 );
Console. writeline ("member3 = '{0}'", member3 );
Console. writeline ("member4 = '{0}'", member4 );
Console. writeline ("member5 = '{0}'", member5 );
}
}

3. Basic serialization vs custom serialization ):

The. NET Framework provides two types of serialization: Basic serialization and custom serialization. It is worth noting that the serialization method is different from the serialization format mentioned above. Serialization means. net Framework converts program data into a format that can be stored and transmitted, no matter what type of formatter the programmer uses (binary or XML ). The serialized format indicates whether the program data is converted into binary format or XML format.

The simplest way to complete serialization is to make. the Net Framework automatically completes the entire process for us without having to worry about how it is implemented internally. This method is the "Basic serialization" mentioned above ". In this way, all we need to do is to mark the class with the [serializable ()] attribute. The. NET Framework then calls the object of the class and converts it to the desired format. At the same time, you can also control that some of the fields are not serialized by marking the field with the [nonserialized ()] attribute as described earlier. In this way, the most simple and basic serialization work is completed, but you do not know how it is implemented internally. At the same time, you cannot further control the program behavior in the serialization process.

If you want to gain greater control over serialization, you must use the "Custom serialization" method. By using this method, you can fully control which parts of the class can be serialized and which cannot be, and you can also control how to serialize them. The advantage of using this method is to overcome the problems encountered by basic serialization. After a class object is serialized and stored in a file using basic serialization, assume that the object originally has three fields. If a field is added to the object, if this object is deserialized from the file, the number of fields is inconsistent. This problem cannot be solved by basic serialization. It can only be solved by using custom serialization.

Before introducing custom serialization, I will first introduce the code of the Instance program used in the process. This is a time schedule program, which requires the conversion of different time formats. Therefore, the serialization mechanism can be used to solve this problem.

Using system;
Using system. runtime. serialization;

Namespace serializationsample {
[Serializable ()]
Public class schedule {
Protected system. datetime start;
Protected system. datetime end;
// The number of milliseconds to increase during each interval
Protected long interval;

Public System. datetime start {get {return start;} set {start = value ;}}
Public System. datetime end {get {return end;} set {end = value ;}}
Public long interval {get {return interval;} set {interval = value ;}}
Public schedule (system. datetime start, system. datetime end, long interval ){
Start = start;
End = end;
Interval = interval;
}

// If the end time is reached, the end time is returned; otherwise, the next running time is returned.
Public System. datetime nextruntime {
Get {
System. timespan Ts = new system. timespan (end. Ticks-System.DateTime.Now.Ticks );
If (TS. milliseconds> 0 ){
Return System. datetime. Now. addmilliseconds (interval );
} Else {
Return end;
}
}
}
}
}
 

Custom serialization:

Next I will introduce the specific process of custom serialization and deserialization. First, the program class must implement the system. runtime. serialization. iserializable interface, which allows an object to control its own serialization and deserialization processes. So we have to redefine the above class:

[Serializable ()]
Public class schedulecustom: system. runtime. serialization. iserializable

Next, we must call the getobjectdata () Implementation for this interface, that is, we must provide the specific implementation of getobjectdata () in the above class. The function prototype is as follows:

Void getobjectdata (serializationinfo info, streamingcontext context );

The specific implementation of getobjectdata () in the above class is as follows:

Public void getobjectdata (serializationinfo info, streamingcontext context ){
// Use the Info Object to add the items you need to serialize
Info. addvalue ("START", start );
Info. addvalue ("end", end );
Info. addvalue ("interval", interval );
}

However, for such a simple method, readers may not be able to understand the powerful functions of serialization, so I will add something to this method below. If we want to view the output of the "Start" attribute of datetime type during the serialization process, the result will be the default format of the. NET Framework:

2002-12-19t14: 09: 13.3457440-

And for no. net Framework users, or users in other time regions, the time in such a format may be very difficult to understand, therefore, it is necessary to convert the time format to the Greenwich Mean Time Format. Therefore, the getobjectdata () method is modified as follows:

Public void getobjectdata (serializationinfo info, streamingcontext context ){
// Use the Info Object to add the items you need to serialize
// At the same time, convert the time formats of the "Start" and "end" attributes to the Greenwich Mean Time Format
Info. addvalue ("START", system. timezone. currenttimezone. touniversaltime (start ));
Info. addvalue ("end", system. timezone. currenttimezone. touniversaltime (end ));
Info. addvalue ("interval", interval );
Info. addvalue ("timeformat", "UTC ");
}

In this way, we will get the following results when viewing the "Start" attribute during the serialization process:

8/19/2002 9:09:13

At the same time, please note that we add an additional attribute named "timeformat" in the getobjectdata () method, through which we can easily know the time format used in the serialization process. If you are interested, you can also get more information about the time format from the namespace system. Globalization. datetimeformatinfo.

Custom deserialization:

You can call a custom constructor to perform custom deserialization. The constructor is defined as follows:

Public schedulecustom (serializationinfo, streamingcontext context );

In the preceding class, our schedulecustom () method deserializes the time format from Greenwich Mean standard time format to the local time format. Its function implementation is as follows:

Public schedulecustom (serializationinfo info, streamingcontext context ){
This. Start = info. getdatetime ("START"). tolocaltime ();
This. End = info. getdatetime ("end"). tolocaltime ();
This. interval = info. getint32 ("interval ");
}

After custom serialization and custom deserialization, our schedule program becomes in the following format:

Using system;
Using system. runtime. serialization;

Namespace serializationsample {
[Serializable ()]
Public class schedulecustom: system. runtime. serialization. iserializable {
Protected system. datetime start;
Protected system. datetime end;
// The number of milliseconds to increase during each interval
Protected long interval;

Public System. datetime start {get {return start;} set {start = value ;}}
Public System. datetime end {get {return end;} set {end = value ;}}
Public long interval {get {return interval;} set {interval = value ;}}

Public schedulecustom (system. datetime start, system. datetime end, long interval ){
Start = start;
End = end;
Interval = interval;
}

// If the end time is reached, the end time is returned; otherwise, the next running time is returned.
Public System. datetime nextruntime {
Get {
System. timespan Ts = new system. timespan (end. Ticks-System.DateTime.Now.Ticks );
If (TS. milliseconds> 0 ){
Return System. datetime. Now. addmilliseconds (interval );
} Else {
Return end;
}
}
}

Public void getobjectdata (serializationinfo info, streamingcontext context ){
// Use the Info Object to add the items you need to serialize
// At the same time, convert the time formats of the "Start" and "end" attributes to the Greenwich Mean Time Format
Info. addvalue ("START", system. timezone. currenttimezone. touniversaltime (start ));
Info. addvalue ("end", system. timezone. currenttimezone. touniversaltime (end ));
Info. addvalue ("interval", interval );
Info. addvalue ("timeformat", "UTC ");
}

Public schedulecustom (serializationinfo info, streamingcontext context ){
This. Start = info. getdatetime ("START"). tolocaltime ();
This. End = info. getdatetime ("end"). tolocaltime ();
This. interval = info. getint32 ("interval ");
}
}
}
 

Iv. Summary:

This article introduces you. net Framework. After reading this article, you should have a preliminary understanding of the following concepts: binary serialization, XML serialization, basic serialization, and custom serialization should be able to complete some basic serialization applications. Finally, we hope that the serialization mechanism can be used reasonably and effectively to better meet the actual work needs.

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.