I implemented the possibility to add \"properties\" at runtime to objects with special SystemComponent.PropertyDescriptor-s.
Due to the fact that these properties ar
One possibility would be to create a custom ContractResolver that, when serializing a specific object of type TTarget, adds a synthetic ExtensionDataGetter that returns, for the specified target, an IEnumerable of the properties specified in its corresponding DynamicPropertyManager.
First, define the contract resolver as follows:
public class DynamicPropertyContractResolver : DefaultContractResolver
{
readonly DynamicPropertyManager manager;
readonly TTarget target;
public DynamicPropertyContractResolver(DynamicPropertyManager manager, TTarget target)
{
if (manager == null)
throw new ArgumentNullException();
this.manager = manager;
this.target = target;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
if (objectType == typeof(TTarget))
{
if (contract.ExtensionDataGetter != null || contract.ExtensionDataSetter != null)
throw new JsonSerializationException(string.Format("Type {0} already has extension data.", typeof(TTarget)));
contract.ExtensionDataGetter = (o) =>
{
if (o == (object)target)
{
return manager.Properties.Select(p => new KeyValuePair
Then serialize your object as follows:
var obj = new object();
//Add prop to instance
int propVal = 0;
var propManager = new DynamicPropertyManager
Which outputs, as required,
{"Value":3}
Obviously this could be extended to serializing a graph of objects with dynamic properties by passing a collection of dynamic property managers and targets to an enhanced DynamicPropertyContractResolver. The basic idea, of creating a synthetic ExtensionDataGetter (and ExtensionDataSetter for deserialization) can work as long as the contract resolver has some mechanism for mapping from a target being (de)serialized to its DynamicPropertyManager.
Limitation: if the TTarget type already has an extension data member, this will not work.