如何序列化&反序列化静态引用对象

本文关键字:静态 引用 对象 反序列化 序列化 | 更新日期: 2023-09-27 18:11:12

我要序列化&使用BinaryFormatter反序列化一个对象(该对象有引用)。

我期望' deserializedoobject . equals (A.Empty)'与下面的代码相同。但是,结果是不同的。

为了` DeserializedObject == A.Empty `,如何使用serialize/deserialize ?

[Serializable]
public class A
{
    private string ID = null;
    private string Name = null;
    public A()
    { }
    public static A Empty = new A()
    {
        ID = "Empty",
        Name = "Empty"
    };
}
class Program
{
    static void Main(string[] args)
    {
        A refObject = A.Empty; // Add reference with static object(Empty)
        A DeserializedObject;
        //Test
        //before serialization, refObject and A.Empty is Same!!
        if(refObject.Equals(A.Empty))
        {
            Console.WriteLine("refObject and A.Empty is the same ");
        }
        //serialization
        using (Stream stream = File.Create("C:''Users''admin''Desktop''test.mbf"))
        {
            BinaryFormatter bin = new BinaryFormatter();
            bin.Serialize(stream, refObject);
        }
        //Deserialization
        using (Stream stream = File.Open("C:''Users''admin''Desktop''test.mbf", FileMode.Open))
        {
            BinaryFormatter bin = new BinaryFormatter();
            DeserializedObject = (A)bin.Deserialize(stream);
        }
        //compare DeserializedObject and A.Empty again.
        //After deserialization, DeserializedObject and A.Empty is Different!!
        if (DeserializedObject.Equals(A.Empty))
        {
            Console.WriteLine("Same");
        }
        else
            Console.WriteLine("Different");
    }
}

如何序列化&反序列化静态引用对象

原因是它们不同的对象!你可以通过打印它们的GetHashCode()来检查这一点。这样做的原因是在您的代码中:

  1. refObject是a . empty的引用(因此是同一个对象)
  2. DeserialisedObject不是一个副本;这是一个新实例,所以不同的对象

但是DeserializedObject应该包含相同的值(ID和Name)。注意refObject。ID将是与A.Empty.ID相同的对象;DeserialisedObject。ID不会,尽管它应该包含相同数据的(副本)。

如果你只是在测试反序列化是否有效,测试DeserializedObject和A.Empty包含的值是否相同

如果你有一个不可变类型,它有一个或多个表示该类型的标准值的全局单例(在你的例子中是A.Empty),你可以实现IObjectReference接口,并使BinaryFormatter用适当的,等效的全局单例替换该类型的反序列化实例。因此:

[Serializable]
public class A : IObjectReference
{
    private string ID = null;
    private string Name = null;
    public A()
    { }
    public static A Empty = new A()
    {
        ID = "Empty",
        Name = "Empty"
    };
    #region IObjectReference Members
    object IObjectReference.GetRealObject(StreamingContext context)
    {
        if (this.GetType() == Empty.GetType() // Type check because A is not sealed
            && this.ID == Empty.ID
            && this.Name == Empty.Name)
            return Empty;
        return this;
    }
    #endregion
}

和,测试:

public class TestClass
{
    public static void Test()
    {
        A refObject = A.Empty; // Add reference with static object(Empty)
        Test(refObject, true);
        A dummy = new A(); // No global singleton for this one.
        Test(dummy, false);
    }
    private static void Test(A refObject, bool shouldBeEqual)
    {
        Console.WriteLine(string.Format("refObject and A.Empty are {0}.", object.ReferenceEquals(refObject, A.Empty) ? "identical" : "different"));
        var binary = BinaryFormatterHelper.ToBase64String(refObject);
        var DeserializedObject = BinaryFormatterHelper.FromBase64String<A>(binary);
        Console.WriteLine(string.Format("DeserializedObject and A.Empty are {0}.", object.ReferenceEquals(DeserializedObject, A.Empty) ? "identical" : "different"));
        Debug.Assert(object.ReferenceEquals(refObject, A.Empty) == object.ReferenceEquals(DeserializedObject, A.Empty)); // No assert
        Debug.Assert(shouldBeEqual == object.ReferenceEquals(refObject, DeserializedObject)); // No assert
    }
}
public static class BinaryFormatterHelper
{
    public static string ToBase64String<T>(T obj)
    {
        using (var stream = new MemoryStream())
        {
            new BinaryFormatter().Serialize(stream, obj);
            return Convert.ToBase64String(stream.GetBuffer(), 0, checked((int)stream.Length)); // Throw an exception on overflow.
        }
    }
    public static T FromBase64String<T>(string data)
    {
        return FromBase64String<T>(data, null);
    }
    public static T FromBase64String<T>(string data, BinaryFormatter formatter)
    {
        using (var stream = new MemoryStream(Convert.FromBase64String(data)))
        {
            formatter = (formatter ?? new BinaryFormatter());
            var obj = formatter.Deserialize(stream);
            if (obj is T)
                return (T)obj;
            return default(T);
        }
    }
}