Iserializable: назначить существующий объект по десериализации
-
13-09-2020 - |
Вопрос
Наша задача довольно проста, у нас есть график объекта, где каждый объект (IDITEM) имеет уникальный идентификатор. График объекта существует два раза, на клиенте и на серверной машине.
Теперь мы передаем несколько сериализуемых команд на сервер.Команда имеет в качестве полей некоторые идейты.IDITEMS реализуют изореализативный интерфейс и хранят только свой идентификатор в сериализацииНФО.Как:
// The method called when serializing a IDItem.
void GetObjectData(SerializationInfo info, StreamingContext context)
{
// Instead of serializing this object, just save the ID
info.AddValue("ID", this.GetID());
}
.
Проблема в том, как мы можем назначить существующий объект к экземпляру, что Deserializer создает?Очевидно, что-то вроде следующего в изисереализируемом конструкторе не работает, потому что идентификатор «этот» только для чтения:
//does not work
protected IDItem(SerializationInfo info, StreamingContext context)
{
this = GlobalObject.GetIDItem(info.GetString("ID"));
}
.
Так что любая идея, как мы можем назначить существующий объект к десериализованному объекту?
С наилучшими пожеланиями, Thalm
Решение
Вы могут сделать это, создавая прокси-объект, который реализует IObjectReference
и выполняет фальшивую десериализацию.
(Ваш прокси-объект должен будет существовать как на клиенте, так и на сервере, и я полагаю, что ваша версификация типа ETC также должна быть точно такой же на обоих.)
[Serializable]
public class Example : ISerializable
{
// ...
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(ExampleDeserializationProxy));
info.AddValue("ID", this.GetID());
}
}
// ...
[Serializable]
public class ExampleDeserializationProxy : IObjectReference, ISerializable
{
private readonly int _id;
private ExampleDeserializationProxy(
SerializationInfo info, StreamingContext context)
{
_id = info.GetInt32("ID");
}
object IObjectReference.GetRealObject(StreamingContext context)
{
return GlobalObject.GetIDItem(_id);
}
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
throw new NotSupportedException("Don't serialize me!");
}
}
. Другие советы
Вы не можете сделать это напрямую.
вместо сериализации всего объекта, но только включая одно поле, почему бы не только отправить по идентификатору и сделать поиск на клиенте и / или сервере?Если я правильно понимаю, экземпляр этого объекта уже существует на сервере.Не должно быть никаких причин, почему вам нужно будет пройти через определенную версию этого объекта, чтобы снова посмотреть один и тот же объект.
Если идентификатор уникален и хранится в коллекции где-то вместе с объектом, имел идентификатор, передаваемый как строку, или любой материал данных, должен быть достаточным для выполнения поиска в существующей коллекции объектов.