views:

43

answers:

2

Hello overflow,

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

+1  A: 

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.

rakuo15
The problem is, that the IDItems (or subclasses of them) are fiels of a more complex object (a command) which is itself serializable, the process of storing the IDs on serialization and finding the right object on the server should not be done in the command, because the amount of commands is quite high and each would have to store another amount of IDs and so on.. it would be much better if the serialization process could solve this, so that we do not have to care about that when writing a command..
thalm
A: 

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!");
    }
}
LukeH
Excellent, implementing the ISerializable in the helper class to get the ID was the missing part... thanks a lot!
thalm