2015-09-03 2 views
0

Я хочу сериализовать & десериализовать объект (этот объект имеет ссылку) с помощью BinaryFormatter.Как сериализовать и десериализовать статический объект ссылки?

Я ожидал, что «DeserializedObject.Equals (A.Empty)» будет таким же, как ниже кода. но, результат другой.

для того, чтобы «DeserializedObject == A.Empty», как использовать сериализацию/десериализацию?

[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"); 
    } 
} 
+0

ли Вы хотите сохранить * все * ссылку на экземпляры класса 'Ā' когда сериализованные/десериализованными, или просто ссылки на' A.Empty' ? – dbc

ответ

1

Причина этого заключается в том, что они являются различных объектов! Вы можете проверить это, напечатав их GetHashCode(). Причина этого заключается в том, что в вашем коде:

  1. refObject является ссылкой на A.Empty (и, таким образом, тот же объект)
  2. DeserialisedObject НЕ копия; это новый экземпляр и поэтому другой объект

Однако DeserializedObject должен содержать те же значения (ID и Name). Обратите внимание, что refObject.ID будет тем же объектом, что и A.Empty.ID; DeserialisedObject.ID не будет, хотя должен содержать (копию) те же данные.

Если вы просто проверяете работу десериализации, проверьте, что значения, содержащиеся в DeserializedObject и A.Empty, одинаковы.

+0

Спасибо за ваш ответ, но я надеюсь сохранить ссылку. (refObject - ссылка на A.Empty) -------- Deserializing ------- DeserializedObject - это ссылка на A.Empty. этот результат невозможно? Я надеюсь сохранить ссылки на объекты после десериализации. – SSgi88

+1

Это не так, как работает десериализация. Он всегда будет создавать новый объект - он действительно не может работать иначе. –

1

Если у вас есть неизменный тип, который имеет один или несколько глобальных одиночка, которые представляют собой стандартные значения типа (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); 
     } 
    } 
} 
Смежные вопросы