Странное поведение бинарной сериализации .NET в словаре <Key, Value>
Я столкнулся, по крайней мере, с моими ожиданиями, странным поведением в двоичной сериализации .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");
}
}
Ответы
Ответ 1
Я могу воспроизвести проблему. Посмотрел вокруг Google и нашел это: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94265, хотя я не уверен, что это то же самое, похоже, похоже.
EDIT:
Я думаю, что добавление этого кода может устранить проблему?
public void OnDeserialization(object sender)
{
this.Dictionary.OnDeserialization(sender);
}
Нет времени для исчерпывающего тестирования, и я хочу победить Марка на ответ; -)
Ответ 2
Да, вы обнаружили раздражающую причуду в десериализации 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);
}
Ответ 3
Интересный... для информации, я попробовал его с помощью подхода, основанного на атрибутах (ниже), и он ведет себя так же... очень любопытно! Я не могу это объяснить - я просто отвечаю, чтобы подтвердить воспроизведение, и упомянуть поведение [OnDeserialized]
:
[OnDeserialized] // note still not added yet...
private void OnDeserialized(StreamingContext context) {...}
Изменить - найдена проблема "connect" здесь. Попробуйте добавить к вашему обратному сообщению:
Dictionary.OnDeserialization(this);