我在.NET的二进制序列化中遇到了一个奇怪的行为,至少在我的期望中。
加载的Dictionary
的所有项目都会在OnDeserialization
回调后添加到其父级。相反,List
则相反。这在真实世界的存储库代码中可能非常烦人,例如,当您需要向字典项添加一些委托时。请检查示例代码并观察断言。
这是正常行为吗?
[Serializable]
public class Data : IDeserializationCallback
{
public List<string> List { get; set; }
public Dictionary<string, string> Dictionary { get; set; }
public Data()
{
Dictionary = new Dictionary<string, string> { { "hello", "hello" }, { "CU", "CU" } };
List = new List<string> { "hello", "CU" };
}
public static Data Load(string filename)
{
using (Stream stream = File.OpenRead(filename))
{
Data result = (Data)new BinaryFormatter().Deserialize(stream);
TestsLengthsOfDataStructures(result);
return result;
}
}
public void Save(string fileName)
{
using (Stream stream = File.Create(fileName))
{
new BinaryFormatter().Serialize(stream, this);
}
}
public void OnDeserialization(object sender)
{
TestsLengthsOfDataStructures(this);
}
private static void TestsLengthsOfDataStructures(Data data)
{
Debug.Assert(data.List.Count == 2, "List");
Debug.Assert(data.Dictionary.Count == 2, "Dictionary");
}
}
答案 0 :(得分:10)
是的,你在Dictionary<TKey, TValue>
反序列化中发现了一个烦人的怪癖。您可以通过手动调用字典的OnDeserialization()
方法来解决它:
public void OnDeserialization(object sender)
{
Dictionary.OnDeserialization(this);
TestsLengthsOfDataStructures(this);
}
顺便说一下,您还可以使用[OnDeserialized]
属性而不是IDeserializationCallback
:
[OnDeserialized]
public void OnDeserialization(StreamingContext context)
{
Dictionary.OnDeserialization(this);
TestsLengthsOfDataStructures(this);
}
答案 1 :(得分:8)
我可以重现这个问题。看看谷歌并找到了这个:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94265虽然我不确定它是完全相同的问题,但看起来非常相似。
编辑:
我认为添加此代码可能已经解决了问题?
public void OnDeserialization(object sender)
{
this.Dictionary.OnDeserialization(sender);
}
没有时间进行详尽的测试,我想要击败Marc得到答案; - )
答案 2 :(得分:4)
有趣......对于信息,我尝试使用基于属性的方法(下面),它的行为相同......非常好奇!我无法解释 - 我只是回复确认转载,并提及[OnDeserialized]
行为:
[OnDeserialized] // note still not added yet...
private void OnDeserialized(StreamingContext context) {...}
修改 - 找到“连接”问题here。尝试添加回调:
Dictionary.OnDeserialization(this);