设计一个可以序列化的c#单例模式类

我们知道单例模式是不能序列化的,会生成另一个实例,从而破坏了单例模式,在C#里,通过实现接口ISerializable,从而订制序列化,这个接口的方法的签名void GetObjectData(SerializationInfo info, StreamingContext context),这个方法必须用特性保护起来,避免被乱用,应用特性[SecurityPermission(SecurityAction.Demand,SerializationFormatter =true)]可以达到目的。具体的单例模式类是这样,单例模式采用嵌套类实现。

namespace SingletonSerializationTest
{
    [Serializable]
    sealed class Singeton:ISerializable
    {
        private string name;

        public string Name { get => name; set => name = value; }
        private Singeton() { }        
        
        [SecurityPermission(SecurityAction.Demand,SerializationFormatter =true)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.SetType(typeof(SingetonSerializationHelp));
        }
        
        public static Singeton Instance
        {
            get { return Nested._instance; }
        }

        [Serializable]
        private class SingetonSerializationHelp : IObjectReference
        {
            public object GetRealObject(StreamingContext context)
            {
                return Instance;
            }
        }

        [Serializable]
       internal  class Nested
        {
            internal static readonly Singeton _instance = null;
            static Nested()
            {
                _instance = new Singeton();
            }
        }
    }
}

GetObjectData就是用info.SetType(typeof(SingetonSerializationHelp))设置一下类型,SingetonSerializationHelp是个嵌套的辅助类,实现接口IObjectReference。

我们来实际运行 一下序列化,看看还是不是单例。

 class Program
    {
        static void Main(string[] args)
        {
            Singeton singeton1 = Singeton.Instance;
            singeton1.Name = "王平";
            Singeton singeton2 = null;
            
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();               
                formatter.Context = new StreamingContext(StreamingContextStates.Clone);
                formatter.Serialize(stream, singeton1);
                stream.Position = 0;
                singeton2 = (Singeton)formatter.Deserialize(stream);
            }
            Console.WriteLine(singeton1.Name);
            Console.WriteLine(singeton2.Name);
            Console.WriteLine($"singeton1==singeton2吗 {singeton1 == singeton2}");            

            Console.ReadKey();
        }
    }

运行结果令人满意,如果去掉ISerializable接口及方法,比较结果就是false。

你可能感兴趣的:(设计一个可以序列化的c#单例模式类)