Serialize a Static Class?

What happens if we serialize a static class? Can more than one instance of the static class be created if we serialize it?

[Serializable]
public static class MyClass
{
    public static MyClass()
    {

    }

    public static bool IsTrue()
    {
       return true;
    }
}

Suppose I XmlSerialize the object to a XML file, and at a later time I de-serialize back to a object. Another copy exists in the memory (created when somone instintiated the static calss for the first time). Will, there be two copy of the of the object? If yes, can we stop that? Does it apply to any class which follows the singleton pattern?


Solution 1:

There are never any instances of static classes: they are both abstract and sealed in the IL, so the CLR will prevent any instances being created. Therefore there is nothing to serialize. Static fields are never serialized, and that's the only sort of state that a static class can have.

Your question about XML serialization makes no sense, as no-one can ever have created an instance of the static class to start with.

Solution 2:

You can't serialize static classes (or any class whatsoever) using built-in .NET serialization features. You can only serialize instances of classes.

Solution 3:

You may create the following class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Soap;
using System.Reflection;
using System.IO;

namespace SerializeStatic_NET
{
    public class SerializeStatic
    {
        public static bool Save(Type static_class, string filename)
        {
            try
            {
                FieldInfo[] fields = static_class.GetFields(BindingFlags.Static | BindingFlags.Public);
                object[,] a = new object[fields.Length,2];
                int i = 0;
                foreach (FieldInfo field in fields)
                {
                    a[i, 0] = field.Name;
                    a[i, 1] = field.GetValue(null);
                    i++;
                };
                Stream f = File.Open(filename, FileMode.Create);
                SoapFormatter formatter = new SoapFormatter();                
                formatter.Serialize(f, a);
                f.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static bool Load(Type static_class, string filename)
        {
            try
            {
                FieldInfo[] fields = static_class.GetFields(BindingFlags.Static | BindingFlags.Public);                
                object[,] a;
                Stream f = File.Open(filename, FileMode.Open);
                SoapFormatter formatter = new SoapFormatter();
                a = formatter.Deserialize(f) as object[,];
                f.Close();
                if (a.GetLength(0) != fields.Length) return false;
                int i = 0;
                foreach (FieldInfo field in fields)
                {
                    if (field.Name == (a[i, 0] as string))
                    {
                        field.SetValue(null, a[i,1]);
                    }
                    i++;
                };                
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}

You must define a reference to System.Runtime.Serialization.Formatters.Soap.

Say, in your program you want to save the following static class:

public static class A
{
    public static string s;
    public static int i;
    public static double z;
}

You may use the following code:

bool ok = SerializeStatic.Save(typeof(A), "c:\\tests\\a.dat");

If you want to load the saved data (in the same program or in another program), use the following code:

bool ok2 = SerializeStatic.Load(typeof(A), "c:\\tests\\a.dat");

The fields A.s, A.i, A.z will get the new, loaded values.

Solution 4:

Why not just use a temporary instance class that is a mirror of the static class?

[XmlRoot]
public class SerializeClass
{
    public int Number {
        get;
        set;
    }
}

public static class SerializedClass {

    public static int Number {
        get;
        set;
    }


    public static void Serialize(Stream stream) {

        SerializeClass obj = new SerializeClass();
        obj.Number = Number;

        XmlSerializer serializer = new XmlSerializer(typeof(SerializeClass));
        serializer.Serialize(stream, obj);
    }

    public static void Deserialize(Stream stream) {

        XmlSerializer serializer = new XmlSerializer(typeof(SerializeClass));
        SerializeClass obj = (SerializeClass)serializer.Deserialize(stream);

        Number = obj.Number;
    }
}

I know it's a bit of a hack, but it acheives the same purpose, while still allowing Refactor before runtime, and value validation during runtime.