我们知道单例模式可以有以下几种方式:
- 饿汉方式
- 懒汉方式
- 双重检查加锁懒汉方式
- 内部类方式
- 枚举方式
[Serializable]
public class SingletonNew : ISerializable
{
private SingletonNew()
{
}
public class SingletonNew : ISerializable
{
private SingletonNew()
{
}
private static class SingletonFactory
{
public static SingletonNew instance = new SingletonNew();
}
public static SingletonNew GetInstance()
{
return SingletonFactory.instance;
}
{
public static SingletonNew instance = new SingletonNew();
}
public static SingletonNew GetInstance()
{
return SingletonFactory.instance;
}
}
private static void Main(string[] args)
{
var instance = SingletonNew.GetInstance();
StringBuilder sb = new StringBuilder();
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, instance);
ms.Position = 0;
byte[] bytes = ms.ToArray();
foreach (byte bt in bytes)
{
sb.Append(string.Format("{0:X2}", bt));
}
}
var newInstance = FromBinary<SingletonNew>(sb.ToString());
Console.WriteLine(ReferenceEquals(instance,newInstance));
Console.Read();
}
/// <summary>
/// BinaryFormatter反序列化
/// </summary>
/// <param name="str">字符串序列</param>
public static T FromBinary<T>(string str)
{
int intLen = str.Length / 2;
byte[] bytes = new byte[intLen];
for (int i = 0; i < intLen; i++)
{
int ibyte = Convert.ToInt32(str.Substring(i * 2, 2), 16);
bytes[i] = (byte)ibyte;
}
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (T)formatter.Deserialize(ms);
}
}
{
var instance = SingletonNew.GetInstance();
StringBuilder sb = new StringBuilder();
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, instance);
ms.Position = 0;
byte[] bytes = ms.ToArray();
foreach (byte bt in bytes)
{
sb.Append(string.Format("{0:X2}", bt));
}
}
var newInstance = FromBinary<SingletonNew>(sb.ToString());
Console.WriteLine(ReferenceEquals(instance,newInstance));
Console.Read();
}
/// <summary>
/// BinaryFormatter反序列化
/// </summary>
/// <param name="str">字符串序列</param>
public static T FromBinary<T>(string str)
{
int intLen = str.Length / 2;
byte[] bytes = new byte[intLen];
for (int i = 0; i < intLen; i++)
{
int ibyte = Convert.ToInt32(str.Substring(i * 2, 2), 16);
bytes[i] = (byte)ibyte;
}
BinaryFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(bytes))
{
return (T)formatter.Deserialize(ms);
}
}
}
得到的结果为false
我们知道在java中我们可以通过写覆盖方法
private
Object
readResolve()
达到序列化同一实例的目的,同理.NET中也是通过ISerializable中GetObjectData方法的实现来达到目的。如下:
[Serializable]
public class SingletonNew : ISerializable
{
private SingletonNew()
{
}
private static class SingletonFactory
{
public static SingletonNew instance = new SingletonNew();
}
public static SingletonNew GetInstance()
{
return SingletonFactory.instance;
}
//防止序列化形成多个实例
public void GetObjectData(
SerializationInfo info, StreamingContext context)
{
// Instead of serializing this object,
// serialize a SingletonSerializationHelp instead.
info.SetType(typeof (SingletonSerializationHelper));
// No other values need to be added.
}
}
[Serializable]
public
class SingletonSerializationHelper : IObjectReference
{
// This object has no fields (although it could).
// GetRealObject is called after this object is deserialized.
public Object GetRealObject(StreamingContext context)
{
// When deserialiing this object, return a reference to
// the Singleton object instead.
return SingletonNew.GetInstance();
}
}
这样情况下得到的结果就是true
原理很简单,在反序列化的过程中,不再创建新的实例来接受反序列化的值,而是直接用已存在的单例。所以反序列化之后的实例还是唯一的
个人见解,勿喷!谢谢