Подтвердить что ты не робот

Странное поведение бинарной сериализации .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");
    }
}
4b9b3361

Ответ 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);