If you separate your serialization concerns from your business layer, it should help find you some flexibility to hammer out a solution. Have 99% of your API work with your business object (which updates timestamps when properties update), then only convert to/from some data-transfer-object (DTO) for serialization purposes only.
For example, given some business object like this:
public class MyObject
{
public DateTime SomeValueUpdated { get; private set; }
private double _SomeValue;
public double SomeValue
{
get
{
return _SomeValue;
}
set
{
SomeValueUpdated = DateTime.Now;
_SomeValue = value;
}
}
public MyObject()
{
}
//for deserialization purposes only
public MyObject(double someValue, DateTime someValueUpdated)
{
this.SomeValue = someValue;
this.SomeValueUpdated = someValueUpdated;
}
}
You could have a matching DTO like this:
public class MyObjectDTO
{
public DateTime SomeValueUpdated { get; set; }
public double SomeValue { get; set; }
}
Your DTO can be specially adorned with various XML schema altering attributes, or you can manage the timestamps however you see fit and your business layer doesn't know and doesn't care.
When it comes time to serialize or deserialize the objects, run them through a converter utility:
public static class MyObjectDTOConverter
{
public static MyObjectDTO ToSerializable(MyObject myObj)
{
return new MyObjectDTO {
SomeValue = myObj.SomeValue,
SomeValueUpdated = myObj.SomeValueUpdated
};
}
public static MyObject FromSerializable(MyObjectDTO myObjSerialized)
{
return new MyObject(
myObjSerialized.SomeValue,
myObjSerialized.SomeValueUpdated
);
}
}
If you wish, you can make any of the properties or constructors of MyObject
to be internal
so only your conversion utility can access them. (For example, maybe you don't want to have the public MyObject(double someValue, DateTime someValueUpdated)
constructor publicly accessible)