Consider the following POD type of class:
public class Price { public decimal OfferPrice { get; set; } }
objects from this class are retrieved from a server so let's decorate it with Serializable
[Serializable]
public class Price { public decimal OfferPrice { get; set; } }
Now there's two clients on different machines retrieving these objects. They wont send prices. They all get a copy of Price's assembly.
Now the class is expanded with BonusPrice.
[Serializable]
public class Price {
public decimal OfferPrice { get; set; }
public decimal BonusPrice { get; set; }
}
The new assembly is deployed to the server, to one of the clients but NOT the other. So the older versioned client will crash when (de)serializing Price objects.
The client with the old version does not need the BonusPrice field so it would be nice that it keeps working when there's a version difference. Therefore I'm thinking of implementing ISerializable from the beginning so the first and second version would look like:
// version 1.0
[Serializable]
public class Price : ISerializable {
protected Price(SerializationInfo info, StreamingContext context) {
OfferPrice = info.GetDecimal("op");
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("op", OfferPrice);
}
}
// version 2.0
[Serializable]
public class Price : ISerializable {
protected Price(SerializationInfo info, StreamingContext context) {
OfferPrice = info.GetDecimal("op");
BonusPrice = info.GetDecimal("bp");
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("op", OfferPrice);
info.AddValue("bp", BonusPrice);
}
}
So now when the one client does not get updated to version 2 it will still keep on deserializing only OfferPrice and not crash. When it's updated at some point it will use BonusPrice automatically.
My question: is implementing ISerializable a good way to go with version control when only reading objects? How are these problems usually solved?
You can use the OptionalFieldAttribute to control versioning of BinaryFormatter and SoapFormatter.
The OptionalFieldAttribute has the VersionAdded property. In version 2.0 of the .NET Framework, this is not used. However, it is important to set this property correctly to ensure that the type will be compatible with future serialization engines.
The property indicates which version of a type a given field has been added. It should be incremented by exactly one (starting at 2) every time the type is modified
Also there are other ways like Serialization Callbacks, SerializationBinder, ISerializable etc..
Refer Version Tolerant Serialization for more info.
From my point of view you are trying to mix two protocols versions in one contract. In your example it works but in practice often it's hard to unify new protocol so it's better to leave them separate. In other words, your server has to support both versions independently. Take a look at OData Protocol Versioning
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With