序列化静态类?

Bha*_*kar 39 c# singleton serialization

如果我们序列化静态类会发生什么?如果我们序列化它,可以创建多个静态类的实例吗?

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

    }

    public static bool IsTrue()
    {
       return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

假设我将对象XmlSerialize为XML文件,稍后我反序列化回一个对象.另一个副本存在于内存中(当somone第一次直观地表达静态calss时创建).请问,有两个副本的对象?如果是的话,我们可以阻止吗?它是否适用于遵循单例模式的任何类?

Jon*_*eet 55

从来没有静态类的任何实例:它们都是抽象的并且在IL中是密封的,因此CLR将阻止创建任何实例.因此没有什么可序列化的.静态字段永远不会被序列化,这是静态类可以拥有的唯一状态.

关于XML序列化的问题毫无意义,因为没有人能够创建静态类的实例.

  • 这个怎么样:`public static class Constants { public const string Con1 = "con1"; public const string Con2 = "con2"; }` 我想动态地将它传递给 javascript,在这种情况下,某种序列化方式是有意义的。是的,今天 _serialize_ 一词的含义可能略有不同。 (3认同)

Meh*_*ari 17

您无法static使用内置的.NET序列化功能序列化类(或任何类).您只能序列化类的实例.


Mik*_*nov 14

您可以创建以下类:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您必须定义对System.Runtime.Serialization.Formatters.Soap的引用.

比如,在您的程序中,您要保存以下静态类:

public static class A
{
    public static string s;
    public static int i;
    public static double z;
}
Run Code Online (Sandbox Code Playgroud)

您可以使用以下代码:

bool ok = SerializeStatic.Save(typeof(A), "c:\\tests\\a.dat");
Run Code Online (Sandbox Code Playgroud)

如果要加载保存的数据(在同一程序或其他程序中),请使用以下代码:

bool ok2 = SerializeStatic.Load(typeof(A), "c:\\tests\\a.dat");
Run Code Online (Sandbox Code Playgroud)

字段As,Ai,Az将获得新的加载值.


Sil*_*erX 8

为什么不使用一个临时实例类作为静态类的镜像?

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道它有点像黑客,但它实现了相同的目的,同时在运行时仍允许重构,并在运行时进行值验证.