SoFunction
Updated on 2025-03-08

C# serialization detailed explanation example


Several serialization techniques:
1) Binary serialization maintains type fidelity, which is useful for preserving the state of an object between different calls of the application. For example, by serializing objects to the clipboard, objects can be shared between different applications. You can serialize objects to streams, disks, memory, networks, and more. Remote processing uses serialization "by value" to pass objects between computers or application domains.
2) XML serialization only serializes public attributes and fields, and does not maintain type fidelity. This is useful when you want to provide or use data without restricting the application that uses that data. Since XML is an open standard, it is a great choice for sharing data over the web. SOAP is also an open standard, which makes it an attractive option.
3) Serialize and deserialize type instances into XML streams or documents (or JSON format) using the provided data contract. Often used in WCF communication.

BinaryFormatter

Serialization may be defined as a process of storing the state of an object into a storage medium. In this process, the public and private fields of the object and the name of the class (including the assembly containing the class) are converted into a byte stream and then written to the data stream. When the object is later deserialized, an exact copy of the original object is created.

1. The easiest way to make a class serializable is to use the Serializable property tag as shown below.

2. Selective serialization

By tagging member variables with the NonSerialized property, they can be prevented from being serialized

3. Custom serialization

1) Run custom methods during and after serialization
Best practice is also the easiest way (introduced in .Net Framework version 2.0) that is, to apply the following properties to the method used to correct data during and after serialization:

Copy the codeThe code is as follows:

OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
OnSerializingAttribute

Specific things are as follows:

Copy the codeThe code is as follows:

// This is the object that will be serialized and deserialized.
[Serializable()] 
public class TestSimpleObject 
{
    // This member is serialized and deserialized with no change.
    public int member1;

    // The value of this field is set and reset during and
    // after serialization.
    private string member2;

    // This field is not serialized. The OnDeserializedAttribute
    // is used to set the member value after serialization.
    [NonSerialized()]
    public string member3;

    // This field is set to null, but populated after deserialization.
    private string member4;

    // Constructor for the class.
    public TestSimpleObject()
    {
  member1 = 11;
  member2 = "Hello World!";
  member3 = "This is a nonserialized value";
  member4 = null;
    }

    public void Print()
    {
  ("member1 = '{0}'", member1);
  ("member2 = '{0}'", member2);
  ("member3 = '{0}'", member3);
  ("member4 = '{0}'", member4);
    }

    [OnSerializing()]
    internal void OnSerializingMethod(StreamingContext context)
    {
  member2 = "This value went into the data file during serialization.";
    }

    [OnSerialized()]
    internal void OnSerializedMethod(StreamingContext context)
    {
  member2 = "This value was reset after serialization.";
    }

    [OnDeserializing()]
    internal void OnDeserializingMethod(StreamingContext context)
    {
  member3 = "This value was set during deserialization";
    }

    [OnDeserialized()]
    internal void OnDeserializedMethod(StreamingContext context)
    {
  member4 = "This value was set after deserialization.";
    }   
}

2) Implement ISerializable interface

Default serialization should not be used for classes marked with Serializable attributes and are declarative or imperatively safe at the class level or on their constructors. Instead, these classes should always implement the ISerializable interface. Implementing ISerializable involves implementing the GetObjectData method and special constructors used when deserializing objects.

Specific examples are as follows:

Copy the codeThe code is as follows:

[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 = ("k");
  }
[SecurityPermissionAttribute(,SerializationFormatter
=true)]
  public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    ("i", n1);
    ("j", n2);
    ("k", str);
  }
}

Notice:

The constructor is not called when deserializing an object. This constraint is imposed on deserialization for performance reasons. However, this violates some common conventions between the runtime library and the object writer, and developers should make sure they understand the consequences when marking the object as serializable.

SoapFormatter

Serialize and deserialize the graphical serialization and deserialization of an object or an entire connected object in SOAP format. The basic usage is similar to BinaryFormatter. The SoapFormatter and BinaryFormatter classes implement the IRemotingFormatter interface to support remote procedure calls (RPCs), and the IFormatter interface (inherited by IRemotingFormatter) to support the serialization of object graphics. The SoapFormatter class also supports RPCing of ISoapMessage objects without having to use the IRemotingFormatter feature.

XmlSerializer

Serialize objects into and deserialize objects from XML documents. XmlSerializer gives you control over how objects are encoded into XML.

XML serialization is a process of converting the public properties and fields of an object into a sequence format (here is XML) for storage or transmission. Deserialization is to recreate the original state object from the XML output. Therefore, serialization can be considered as a way to save the state of an object to a stream or buffer. For example, use the XmlSerializer class to encode XML Web services messages.

example:

C# code

Copy the codeThe code is as follows:

public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

Serialized XML

Copy the codeThe code is as follows:

<MyClass>
  <MyObjectProperty>
  <ObjectName>My String</ObjectName>
  </MyObjectProperty>
</MyClass>

You can also control the output of XML through tags

1. Default value

DefaultValueAttribute

2. Filter a certain attribute or field

 XmlIgnoreAttribute

3. Rewrite the default serialization logic
4. Serialize objects into SOAP-encoded XML streams

Notice

XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections). To serialize all fields and properties of an object (public and private), use BinaryFormatter instead of XML serialization.

DataContractSerializer

Use the provided data contract to serialize and deserialize type instances into XML streams or documents. This type cannot be inherited.

DataContractSerializer is used to serialize and deserialize data sent in Windows Communication Foundation (WCF) messages. By applying the DataContractAttribute property (Attribute) to the class and the DataMemberAttribute property (Attribute) to the class members, you can specify the properties and fields to be serialized.

Steps to use:

1) DataContractSerializer is used in conjunction with DataContractAttribute and DataMemberAttribute classes.

To prepare to serialize a class, apply DataContractAttribute to the class. For each member of the class that returns the data to be serialized, apply DataMemberAttribute. You can serialize fields and properties regardless of their accessibility level: private, protected, internal, protected internal, or public.

2) Add to a collection of known types

When serializing or deserializing an object, the DataContractSerializer must "known" the type. First, create an instance of the class that implements IEnumerable<T> (such as List<T>) and add a known type to the collection. Then, create an instance of DataContractSerializer using one of the overloads that accepts IEnumerable<T> (for example, [M:.#ctor(,{}]).

Specific examples:

Copy the codeThe code is as follows:

namespace DataContractSerializerExample
{
    using System;
    using ;
    using ;
    using ;
    using ;

    // You must apply a DataContractAttribute or SerializableAttribute
    // to a class to have it serialized by the DataContractSerializer.
    [DataContract(Name = "Customer", Namespace = "")]
    class Person : IExtensibleDataObject
    {
  [DataMember()]
  public string FirstName;
  [DataMember]
  public string LastName;
  [DataMember()]
  public int ID;

  public Person(string newfName, string newLName, int newID)
  {
FirstName = newfName;
LastName = newLName;
ID = newID;
  }

  private ExtensionDataObject extensionData_Value;

  public ExtensionDataObject ExtensionData
  {
get
{
    return extensionData_Value;
}
set
{
    extensionData_Value = value;
}
  }
    }

    public sealed class Test
    {
  private Test() { }

  public static void Main()
  {
try
{
    WriteObject("");
    ReadObject("");

}

catch (SerializationException serExc)
{
    ("Serialization Failed");
    ();
}
catch (Exception exc)
{
    (
    "The serialization operation failed: {0} StackTrace: {1}",
    , );
}

finally
{
    ("Press <Enter> to exit....");
    ();
}
  }

  public static void WriteObject(string fileName)
  {
(
    "Creating a Person object and serializing it.");
Person p1 = new Person("Zighetti", "Barbara", 101);
FileStream writer = new FileStream(fileName, );
DataContractSerializer ser =
    new DataContractSerializer(typeof(Person));
(writer, p1);
();
  }

  public static void ReadObject(string fileName)
  {
("Deserializing an instance of the object.");
FileStream fs = new FileStream(fileName,
);
XmlDictionaryReader reader =
    (fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(Person));

// Deserialize the data and read it from the instance.
Person deserializedPerson =
    (Person)(reader, true);
();
();
(("{0} {1}, ID: {2}",
, ,
));
  }
    }

DataContractJsonSerializer

Serializes objects to JavaScript object notation (JSON), and deserializes JSON data to objects. This type cannot be inherited.

The specific use is similar to DataContractSerializer. I won't go into details here.

The following is a summary of the use of these methods, hoping to bring some help to everyone.

Copy the codeThe code is as follows:

using System;
using ;
using ;
using ;
using ;
using ;
using ;
using ;
using ;
using ;

namespace SerializerSample
{
    /// <summary>
/// Serialization help class
    /// </summary>
    public sealed class SerializeHelper
    {
#region DataContract serialization
  /// <summary>
/// DataContract serialization
  /// </summary>
  /// <param name="value"></param>
  /// <param name="knownTypes"></param>
  /// <returns></returns>
  public static string SerializeDataContract(object value, List<Type> knownTypes = null)
  {
DataContractSerializer dataContractSerializer = new DataContractSerializer((), knownTypes);

using (MemoryStream ms = new MemoryStream())
{
    (ms, value);
    (0, );
    using (StreamReader sr = new StreamReader(ms))
    {
  return ();
    }
}
  }
  /// <summary>
/// DataContract deserialization
  /// </summary>
  /// <typeparam name="T"></typeparam>
  /// <param name="xml"></param>
  /// <returns></returns>
  public static T DeserializeDataContract<T>(string xml)
  {
using (MemoryStream ms = new MemoryStream(Encoding.(xml)))
{
    DataContractSerializer serializer = new DataContractSerializer(typeof(T));
    return (T)(ms);
}
  }
  #endregion

#region DataContractJson serialization
  /// <summary>
///  DataContractJson serialization
  /// </summary>
  /// <param name="value"></param>
  /// <returns></returns>
  public static string SerializeDataContractJson(object value)
  {
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(());
using (MemoryStream ms = new MemoryStream())
{   
    (ms, value);
    return Encoding.(());
}
  }
  /// <summary>
///  DataContractJson deserialization
  /// </summary>
  /// <param name="type"></param>
  /// <param name="str"></param>
  /// <returns></returns>
  public static object DeserializeDataContractJson(Type type, string str)
  {
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(type);
using (MemoryStream ms = new MemoryStream(.(str)))
{
    return (ms);
}
  }
  /// <summary>
/// DataContractJson deserialization
  /// </summary>
  /// <typeparam name="T"></typeparam>
  /// <param name="json"></param>
  /// <returns></returns>
  public T DeserializeDataContractJson<T>(string json)
  {
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.(json)))
{
    return (T)(ms);
}
  }
  #endregion

#region XmlSerializer serialization
  /// <summary>
/// Serialize objects into and deserialize objects from XML documents. XmlSerializer gives you control over how objects are encoded into XML.
  /// </summary>
  /// <param name="value"></param>
  /// <returns></returns>
  public static string SerializeXml(object value)
  {
XmlSerializer serializer = new XmlSerializer(());
using (MemoryStream ms = new MemoryStream())
{
    (ms, value);
    (0, );
    using (StreamReader sr = new StreamReader(ms))
    {
  return ();
    }
}
  }
  /// <summary>
///  XmlSerializer deserialization
  /// </summary>
  /// <param name="type"></param>
  /// <param name="str"></param>
  /// <returns></returns>
  public static object DeserializeXml(Type type, string str)
  {
XmlSerializer serializer = new XmlSerializer(type);
byte[] bytes = .(str);
using (MemoryStream ms = new MemoryStream(bytes))
{
    return (ms);
}
  }
  #endregion

#region BinaryFormatter Serialization
  /// <summary>
/// BinaryFormatter Serialization
/// The type must be marked Serializable
  /// </summary>
  /// <param name="obj"></param>
  /// <returns></returns>
  public static string SerializeBinaryFormatter(object obj)
  {
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
    (ms,obj);
    byte[] bytes = ();
    obj = (new MemoryStream(bytes));
//If it is UTF8 format, an error will be reported in deserialization. You can use the Default format, but it is better to pass the parameters into the byte array
    return (bytes);
}
  }

  /// <summary>
/// BinaryFormatter Deserialization
/// The type must be marked Serializable
  /// </summary>
  /// <param name="serializedStr"></param>
  /// <returns></returns>
  public static T DeserializeBinaryFormatter<T>(string serializedStr)
  {
BinaryFormatter formatter = new BinaryFormatter();
byte[] bytes = (serializedStr);
using (MemoryStream ms = new MemoryStream(bytes))
{
    return (T)(ms);
}
  }
  #endregion

#region SoapFormatter Serialization
  /// <summary>
/// SoapFormatter Serialization
/// The type must be marked Serializable
  /// </summary>
  /// <param name="obj"></param>
  /// <returns></returns>
  public static string SerializeSoapFormatter(object obj)
  {
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream())
{
    (ms, obj);
    byte[] bytes = ();
    return Encoding.(bytes);
}
  }
  /// <summary>
/// SoapFormatter deserialization
/// The type must be marked Serializable
  /// </summary>
  /// <param name="serializedStr"></param>
  /// <returns></returns>
  public static T DeserializeSoapFormatter<T>(string serializedStr)
  {
SoapFormatter formatter = new SoapFormatter();
using (MemoryStream ms = new MemoryStream(Encoding.(serializedStr)))
{
    return (T)(ms);
}
  }
  #endregion
    }
}