Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Only On Deserialization

Problem:

I have a class, say Foo, that implements an Id property. Foo must be serializable. Foo.Id should be initialized to a new GUID on initialization of Foo. Foo.Id should not be changable once it has been set. Deserialization will attempt to set the Foo.Id, so it must be made Public.

Private _Id As String=system.Guid.NewGuid.tostring
Public Property Id As String
    Get
        return _Id
    End Get
    Set(ByVal value As String)
        _Id = value
    End Set
End Property

or for c#ers

private string _Id = system.Guid.NewGuid().ToString();
public string Id {
    get { return _Id; }
    set { _Id = value; }
}

Solution Thoughts:

The only solution seems to be to throw a runtime exception when setting Foo.Id, but this will cause a problem during deserialization. So, somehow we must make sure that the exception is only being thrown when an attempt at Set Foo.Id is made outside of the serializer. Some kind of flag or something in the constructor?

Edit, Deserialization method ...

public static Foo DeserializeFromFile(string sFilespec)
{
    Xml.Serialization.XmlSerializer oSerializer = new Xml.Serialization.XmlSerializer(typeof(Foo));
    System.IO.FileStream oStream = new System.IO.FileStream(sFilespec, IO.FileMode.Open);
    Foo oObject = oSerializer.Deserialize(oStream);
    oStream.Close();
    return oObject;
}
like image 430
hmcclungiii Avatar asked Dec 17 '22 07:12

hmcclungiii


1 Answers

I'm not sure if I understand your problem but you can try implementing the ISerializable interface in your class to manually fine-tune the serialization / deserialization processes.

[Serializable]
public class YourClass : ISerializable
{    
    private Guid _Id = Guid.NewGuid();

    public string Id
    {
            get { return _Id; }
            private set { _Id = value; }
    }

    public YourClass() // Normal constructor
    {
       // ...
    }

    // This constructor is for deserialization only
    private YourClass(SerializationInfo information, StreamingContext context)
    {
        Id = (Guid)information.GetValue("Id", typeof(Guid)); // etc
    }

    void ISerializable.GetObjectData(SerializationInfo information,
        StreamingContext context)
    {
        // You serialize stuff like this
        information.AddValue("Id", Id, typeof(Guid)); 
    }
}

Also read up on the SerializationInfo class for more information on serializing and deserializing the most common types.

like image 140
Tamas Czinege Avatar answered Dec 21 '22 23:12

Tamas Czinege