Study on WCF-24: WCF serialization, deserialization, wcf-24
Preface
- WCF contains many encapsulated internal mechanisms, which are not frequently seen during programming. For example, the Message described in the previous article. In this article, I will explain another internal mechanism of WCF, including serialization and deserialization of WCF. Generally, when writing a WCF Service Program, we do not manually serialize or deserialize the WCF data transmission, this is because by default, WCF uses the serialization engine DataContractSerializer to help us with these operations, so developers only need to pay attention to the data object definition itself (such as data protocols and message protocols ), instead of paying attention to the serialization mechanism of Data Objects During WCF transmission.
- DataContractSerializer can perform bidirectional conversion between. NET Framework objects and XML objects. When serializing. NET Framework objects, the serialization Program understands various serialization programming models, including the new data protocol model. This serialization program supports the following types:
Use
DataContractSerializer
Serialization and deserialization
- The most basic method to serialize an object is to pass it to the WriteObject method. This method has three reloads, each of which is used to write data to Stream, XmlWriter, or XmlDictionaryWriter. When you use Stream overload, the output is XML encoded with a UTF-8. When XmlDictionaryWriter is used for heavy load, the serialization program will optimize its output for Binary XML. The reference code is as follows:
User user = new User { ID = 1, Name = "JACK", Age = 20, Nationality = "CHINA" }; FileStream writer = new FileStream(fileName, FileMode.Create); DataContractSerializer ser =new DataContractSerializer(typeof(User)); ser.WriteObject(writer, user); writer.Close();
- The most basic way to deserialize an object is to call the ReadObject method overload. This method has three overloads, each of which is used to read XmlDictionaryReader, XmlReader, or Stream. Note that the Stream overload will create text XmlDictionaryReader that is not protected by any quota. This overload is only used to read trusted data. Note that the object returned by the ReadObject method must be forcibly converted to an appropriate type. The reference code is as follows:
FileStream fs = new FileStream(fileName,FileMode.Open); XmlDictionaryReader reader =XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()); DataContractSerializer ser = new DataContractSerializer(typeof(User)); User deserializedUser =(User)ser.ReadObject(reader, true);
Use
DataContractSerializer
Serialization and deserialization
Example:
- Create a solution named WcfDataContractSerializer and add a console reference program named WcfDataContractSerializer. Modify the Program. cs Code as follows:
Using System; using System. runtime. serialization; using System. IO; using System. xml; namespace WcfDataContractSerializer {class Program {static void Main (string [] args) {try {WriteObject ("DataContractSerializerExample. xml "); ReadObject (" DataContractSerializerExample. xml ");} catch (SerializationException serExc) {Console. writeLine ("serialization failed"); Console. writeLine (serExc. message);} catch (Exception exc) {Console. writeLine ("serialization operation failed: {0} StackTrace: {1}", exc. message, exc. stackTrace);} finally {Console. writeLine ("press <Enter> to exit .... "); Console. readLine () ;}} public static void WriteObject (string fileName) {Console. writeLine ("create a User object and serialize it"); User user = new User {ID = 1, Name = "JACK", Age = 20, Nationality = "CHINA "}; fileStream writer = new FileStream (fileName, FileMode. create); DataContractSerializer ser = new DataContractSerializer (typeof (User); ser. writeObject (writer, user); writer. close (); Console. writeLine ("User object serialized successfully. Please go to the Bin directory of the program to view DataContractSerializerExample. xml file ");} public static void ReadObject (string fileName) {Console. writeLine ("deserialization Instance Object"); FileStream fs = new FileStream (fileName, FileMode. open); XmlDictionaryReader reader = XmlDictionaryReader. createTextReader (fs, new XmlDictionaryReaderQuotas (); DataContractSerializer ser = new DataContractSerializer (typeof (User); User deserializedUser = (User) ser. readObject (reader, true); reader. close (); fs. close (); Console. writeLine ("{0,-10} {1,-10} {2,-10} {3,-10}", "ID", "Name ", "Age", "Nationality"); Console. writeLine ("{0,-10} {1,-10} {2,-10} {3,-10}", deserializedUser. ID. toString (), deserializedUser. name. toString (), deserializedUser. age. toString (), deserializedUser. nationality. toString ();} [DataContract] public class User {[DataMember] public int ID {get; set;} [DataMember] public string Name {get; set ;} [DataMember] public int Age {get; set;} [DataMember] public string Nationality {get; set ;}}}
- The running result is as follows:
Open DataContractSerializerExample. xml in the Bin directory of the program. The result is as follows:
Use
DataContractJsonSerializer
Serialization and deserialization
- You can use DataContractJsonSerializer to convert an object to Json format. If you are used to Json, you can use this serialization engine as the serialization tool for object transmission. The serialization engine is the same as DataContractSerializer and has WriteObject and ReadObject methods. For more information, see the example.
- Note: This serialization engine only performs Json serialization on the message Body of WCF. That is to say, the total message is still in XML format based on SOAP, and only the Body part is converted into a JSON string.
Use
DataContractJsonSerializer
Serialization and deserialization examples
- Add the console application named WcfDataContractJsonSerializer in the previous solution. modify the code of Program. cs as follows:
Using System; using System. runtime. serialization; using System. IO; using System. runtime. serialization. json; using System. text; namespace WcfDataContractJsonSerializer {class Program {static void Main (string [] args) {try {Console. writeLine ("create a User object and serialize it"); User user = new User {ID = 1, Name = "JACK", Age = 20, Nationality = "CHINA "}; string jsonString = Serialize <User> (user); Console. writeLine (jsonString); Console. writeLine ("deserialization Instance Object"); User deserializedUser = Deserialize <User> (jsonString); Console. writeLine ("{0,-10} {1,-10} {2,-10} {3,-10}", "ID", "Name ", "Age", "Nationality"); Console. writeLine ("{0,-10} {1,-10} {2,-10} {3,-10}", deserializedUser. ID. toString (), deserializedUser. name. toString (), deserializedUser. age. toString (), deserializedUser. nationality. toString ();} catch (SerializationException serExc) {Console. writeLine ("serialization failed"); Console. writeLine (serExc. message);} catch (Exception exc) {Console. writeLine ("serialization operation failed: {0} StackTrace: {1}", exc. message, exc. stackTrace);} finally {Console. writeLine ("press <Enter> to exit .... "); Console. readLine () ;}} public static string Serialize <T> (T item) {if (item = null) return string. empty; var serializer = new DataContractJsonSerializer (item. getType (); using (var MS = new MemoryStream () {serializer. writeObject (MS, item); var sb = new StringBuilder (); sb. append (Encoding. UTF8.GetString (ms. toArray (); return sb. toString () ;}} public static T Deserialize <T> (string jsonString) {if (string. isNullOrEmpty (jsonString) return default (T); var ser = new DataContractJsonSerializer (typeof (T); using (var MS = new MemoryStream (Encoding. UTF8.GetBytes (jsonString) {T jsonObject = (T) ser. readObject (MS); return jsonObject ;}} [DataContract] public class User {[DataMember] public int ID {get; set ;}[ DataMember] public string Name {get; set;} [DataMember] public int Age {get; set;} [DataMember] public string Nationality {get; set ;}}}
- The running result is as follows:
Serialization format size comparison
- Three types of serialized format: XML text type, Json text type, and binary type. Next, let's take a small example to see the size of the byte in these three types of serialization. Because we know that the transmission of byte size is particularly important during network data transmission.
- Add the console application named WcfSerializerCompare to the previous solution. modify the code of Program. cs as follows:
Using System; using System. runtime. serialization; using System. IO; using System. runtime. serialization. json; using System. xml; namespace WcfSerializerCompare {class Program {static void Main (string [] args) {MemoryStream stream1 = new MemoryStream (); MemoryStream stream2 = new MemoryStream (); memoryStream stream3 = new MemoryStream (); User user = new User {ID = 1, Name = "JACK", Age = 20, Nationality = "CHINA "}; dataContractSerializer xmlSerializer = new DataContractSerializer (typeof (User); xmlSerializer. writeObject (stream1, user); DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer (typeof (User); jsonSerializer. writeObject (stream2, user); DataContractSerializer binarySerializer = new DataContractSerializer (typeof (User); XmlDictionaryWriter write = XmlDictionaryWriter. createBinaryWriter (stream3); binarySerializer. writeObject (write, user); write. flush (); Console. writeLine ("XML text byte size: {0} bytes", stream1.Length); Console. writeLine ("JSON text byte size: {0} bytes", stream2.Length); Console. writeLine ("the size of binary bytes is {0} bytes", stream3.Length); Console. read () ;}} [DataContract] public class User {[DataMember] public int ID {get; set ;}[ DataMember] public string Name {get; set ;} [DataMember] public int Age {get; set;} [DataMember] public string Nationality {get; set ;}}}
- The running result is as follows:
As shown in the preceding example, the Json text transmission format is the smallest, with only 53 bytes.