Iserializable: назначить существующий объект по десериализации

StackOverflow https://stackoverflow.com/questions/3213410

  •  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!");
    }
}
.

Другие советы

Вы не можете сделать это напрямую.

вместо сериализации всего объекта, но только включая одно поле, почему бы не только отправить по идентификатору и сделать поиск на клиенте и / или сервере?Если я правильно понимаю, экземпляр этого объекта уже существует на сервере.Не должно быть никаких причин, почему вам нужно будет пройти через определенную версию этого объекта, чтобы снова посмотреть один и тот же объект.

Если идентификатор уникален и хранится в коллекции где-то вместе с объектом, имел идентификатор, передаваемый как строку, или любой материал данных, должен быть достаточным для выполнения поиска в существующей коллекции объектов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top