Предполагаю, что вы используете BinaryFormatter
.
BinaryFormatter
- сериализатор графа. Вместо того, чтобы объекты хранятся в чистом дереве, им присваиваются временные идентификаторы объектов и хранятся в том виде, в котором они встречаются. Таким образом, когда объект десериализуется, не гарантируется, что все ссылочные объекты были ранее десериализованы. Таким образом, записи в вашем forwardMap
еще не заполнены.
Обычным обходным путем является добавление логики IDeserializationCallback
в ваш класс и создание ваших inverseMap
и inverseInstance
после того, как все было десериализовано в OnDeserialization . Но Dictionary
также реализует IDeserializationCallback
, что вводит дополнительную проблему секвенсирования: она не гарантируется, что она была вызвана до вашего. В этой теме Microsoft пишет :
Объекты реконструируются изнутри, а вызывающие методы во время десериализации могут иметь нежелательные побочные эффекты, поскольку вызванные методы могут ссылаться на ссылки на объекты, которые не были десериализованы к моменту вызова. Если десериализованный класс реализует IDeserializationCallback, метод OnSerialization будет автоматически вызываться, когда весь объектный граф будет десериализован. На этом этапе все дочерние объекты, на которые делается ссылка, были полностью восстановлены. Хэш-таблица является типичным примером класса, который трудно десериализовать без использования прослушивателя событий, описанного выше. Легко получить пары ключ / значение во время десериализации, но добавление этих объектов обратно в хеш-таблицу может вызвать проблемы, поскольку нет гарантии, что классы, полученные из хеш-таблицы, были десериализованы. Поэтому методы вызова в хеш-таблице на этом этапе нецелесообразны.
blockquote>Таким образом, есть несколько вещей, которые вы могли бы сделать:
- Вместо того, чтобы хранить
Dictionary
, сохраните массив изKeyValuePair
. Это имеет преимущество, заключающееся в том, что ваши двоичные данные проще, но вам требуется выделить массив в вашемGetObjectData()
методе.- Или следовать рекомендациям в справочном источнике словаря :
Т.е. в своем обратном вызове вызовите метод// It might be necessary to call OnDeserialization from a container if the container object also implements // OnDeserialization. However, remoting will call OnDeserialization again. // We can return immediately if this function is called twice. // Note we set remove the serialization info from the table at the end of this method.
OnDeserialization
вашего вложенного словаря перед его использованием:(вместо этого вы можете сделать это в методеpublic partial class BidirectionalDictionary
: IDeserializationCallback { public void OnDeserialization(object sender) { this.forwardMap.OnDeserialization(sender); foreach (KeyValuePair entry in forwardMap) { this.inverseMap.Add(entry.Value, entry.Key); } // inverseInstance will no longer be able to be read-only sicne it is being allocated in a post-deserialization callback. this.inverseInstance = new BidirectionalDictionary (this); } [OnDeserialied]
.)Кстати, это сообщение в блоге утверждает, что безопасно вызывать метод
OnDeserialization
дляHashTable
из конструктора десериализации содержащего класс , а не позжеOnDeserialization
, чтобы вы могли попробовать.