Runtime Serialization in C#

What is Runtime Serialization in C#?

**Runtime Serialization** in C# refers to the ability to serialize and deserialize objects dynamically at runtime, often without requiring predefined attributes like **[Serializable]**. This is commonly used in **reflection-based serialization, dynamic object persistence, and distributed applications**.

Key Features of Runtime Serialization

  • Allows **dynamic object serialization** without modifying class definitions.
  • Uses **reflection** to inspect object properties at runtime.
  • Supports **custom serialization logic** using interfaces like ISerializable.
  • Commonly used in **distributed systems and frameworks like gRPC**.

Using ISerializable for Runtime Serialization

The ISerializable interface allows objects to define **custom serialization logic** dynamically.

Example: Custom Runtime Serialization Using ISerializable

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
class Person : ISerializable
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person() { }

    protected Person(SerializationInfo info, StreamingContext context)
    {
        Name = info.GetString("PersonName");
        Age = info.GetInt32("PersonAge");
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("PersonName", Name);
        info.AddValue("PersonAge", Age);
    }
}

// Writing Runtime Serialized Object
class Program
{
    static void Main()
    {
        Person person = new Person { Name = "Alice", Age = 30 };
        BinaryFormatter formatter = new BinaryFormatter();

        using (FileStream stream = new FileStream("person_runtime.dat", FileMode.Create))
        {
            formatter.Serialize(stream, person);
        }

        Console.WriteLine("Object serialized with runtime logic.");
    }
}

// Output:
// Object serialized with runtime logic.
        

The **ISerializable** interface allows dynamic serialization logic at runtime.

JSON Serialization at Runtime

You can dynamically serialize and deserialize objects at runtime using **System.Text.Json**.

Example: JSON Serialization Using Reflection

using System;
using System.Text.Json;
using System.Reflection;

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Writing JSON Data Dynamically
class Program
{
    static void Main()
    {
        object person = new Person { Name = "Bob", Age = 35 };
        string json = JsonSerializer.Serialize(person);

        Console.WriteLine("Serialized JSON:");
        Console.WriteLine(json);
    }
}

// Output:
// Serialized JSON:
// {"Name":"Bob","Age":35}
        

The **JsonSerializer.Serialize()** method can serialize any object dynamically at runtime.

Using Reflection for Runtime Serialization

**Reflection** allows serialization without requiring a predefined schema.

Example: Serializing an Object Dynamically Using Reflection

using System;
using System.Text.Json;
using System.Reflection;

class Program
{
    static void Main()
    {
        var person = new { Name = "Charlie", Age = 40 }; // Anonymous Type
        PropertyInfo[] properties = person.GetType().GetProperties();

        Console.WriteLine("Serialized Object:");
        foreach (var prop in properties)
        {
            Console.WriteLine($"{prop.Name}: {prop.GetValue(person)}");
        }

        string json = JsonSerializer.Serialize(person);
        Console.WriteLine("\nSerialized JSON:");
        Console.WriteLine(json);
    }
}

// Output:
// Serialized Object:
// Name: Charlie
// Age: 40

// Serialized JSON:
// {"Name":"Charlie","Age":40}
        

Reflection allows **dynamic serialization** of unknown object structures.

Best Practices for Runtime Serialization

  • Use **ISerializable** when custom serialization is required.
  • Use **reflection-based serialization** for **unknown or dynamic objects**.
  • Always **handle exceptions** when deserializing unknown objects.
  • Ensure **performance optimization** by caching reflection calls.