I implemented the possibility to add "properties" at runtime to objects with special SystemComponent.PropertyDescriptor-s.
Due to the fact that these properties are only accessible with the ComponentModel.TypeDescriptor and not via Reflection, the properties work well in WPF environment but not with Serialization.
This is because of all JSON serializers, that I know, use reflection on the type. I analyzed Newtonsoft.Json, System.Json, System.Web.Script.JavaScriptSerializer, System.Runtime.Serialization.Json.
I don't think I can use any of these serializers because none of these allow modifying the retrieval of the properties on an instance (e.g. ContractResolver not possible).
Is there any way to make the JSON serialization work with one of those serializers? Maybe by special configuration, overriding certain methods on the Serializer or similar? Is there another serializer available that fulfills this requirement?
Background:
The idea of the runtime properties is based on this blog entry.
The serialization requirement comes from using dotNetify that serializes the viewmodels to send them to the client.
Currently, I made a fork of dotnetify and made a temporary workaround for the serialization by partially serializing with Newtonsoft.Json and a recursive helper. (You can look at the diff if interested in it: the Fork).
One possibility would be to create a custom
ContractResolverthat, when serializing a specific object of typeTTarget, adds a syntheticExtensionDataGetterthat returns, for the specified target, anIEnumerable<KeyValuePair<Object, Object>>of the properties specified in its correspondingDynamicPropertyManager<TTarget>.First, define the contract resolver as follows:
Then serialize your object as follows:
Which outputs, as required,
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<TTarget>. The basic idea, of creating a syntheticExtensionDataGetter(andExtensionDataSetterfor deserialization) can work as long as the contract resolver has some mechanism for mapping from a target being (de)serialized to itsDynamicPropertyManager.Limitation: if the
TTargettype already has an extension data member, this will not work.