Question

our task is quite simple, we have an object graph where each object (IDItem) has a unique ID. The object graph exists two times, on the client and on the server machine.

Now we pass some serializable commands to the server. The command has as fields some of the IDItems. The IDItems implement the ISerializable interface and only store their ID in the SerializationInfo. Like:

// 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());
}

The problem is, how can we assign the existing object to the instance that the deserializer creates? Obviously something like the following in the ISerializable constructor does not work, because the 'this' identifier is read only:

//does not work   
protected IDItem(SerializationInfo info, StreamingContext context)
{
    this = GlobalObject.GetIDItem(info.GetString("ID"));
}

So any idea how we can Assign an existing object to the deserialized object?

Best Regards, thalm

Was it helpful?

Solution

You might be able to do it by creating a proxy object that implements IObjectReference and performs the fake deserialization.

(Your proxy object would need to exist on both the client and server, and I suppose that your type versioning etc would also need to be exactly the same on both.)

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

OTHER TIPS

You can't do it directly like that.

Instead of serializing the whole object but only including one field, why not just send over the ID and do a lookup on the client and/or server? If I understand correctly, an instance of that object already exists on the server. There should be no reason why you would need to pass over a stripped version of that object just to look up the same object again.

If the ID is unique and stored in a collection somewhere along with the object, having the ID passed as a string, or whatever datatype it is, should be sufficient to perform a lookup in your existing collection of objects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top