JsonObjectContract.ParametrizedConstructor
is marked as Obsolete and says that OverrideCreator
should be used instead. However OverrideCreator
does not set _parametrizedConstructor
or _parameterizedCreator
meaning that if you need to set those values from the outside you must use ParametrizedConstructor
.
Is this intentional? If so why?
Thanks!
Edit 1:
To explain why I'm asking, I have a class in my application that handles serialization (using JSON.Net). This class creates a custom IContractResolver
(based on DefaultContractResolver
) that has a stock set of JsonConverter
s that I wrote for my application. This allows the contracts that are generated to check for the converters once and then be cached.
My serialization class allows callers to pass in their own custom converters. When this is done I create a new IContractResolver
that takes these new converters and the default contract resolver. What I do then is, when resolving the contract for a type, I first get a contract from the default contract resolver. When I get it I then check and see if any of the new converters can handle the type. If they can I 'clone' the json contract and replace the converter with the new one (and cache it).
In this cloning is where I set the ParametrizedConstructor
. I was not doing this originally, as it was marked as deprecated, I set just the OverrideCreator
. I ran into an issue when deserializing Tuple
s. I kept getting an error saying there was no constructor for Tuple. I tried using the stock JsonConvert
to round trip a Tuple
and it worked perfectly. In looking into why it worked with JsonConvert
I found it was because when I 'clone' the contract I was not setting the ParametrizedConstructor
.
Edit 2:
Here is a slimmed example of my contract resolver:
class MyContractResolver : DefaultContractResolver
{
readonly Dictionary<Type, JsonContract> contractDictionary = new Dictionary<Type, JsonContract>();
readonly List<JsonConverter> converters;
readonly IContractResolver resolverToExtend;
public MyContractResolver(List<JsonConverter> converters, IContractResolver resolverToExtend)
{
this.converters = converters;
this.resolverToExtend = resolverToExtend;
}
public override JsonContract ResolveContract(Type type)
{
JsonContract contract;
if (!contractDictionary.TryGetValue(type, out contract))
{
contract = resolverToExtend.ResolveContract(type);
var converter = contract.Converter;
foreach (var baseConverter in converters)
{
if (baseConverter.CanConvert(type))
{
contract = CloneJsonContract(contract, type, baseConverter);
break;
}
}
contractDictionary.Add(type, contract);
}
return contract;
}
static JsonContract CloneJsonContract(JsonContract contract, Type type, JsonConverter customConverter)
{
JsonContract newContract;
// Check contract type and create a new one (JsonArrayContract, JsonDictionaryContract etc)
if (contract is JsonArrayContract)
{
newContract = new JsonArrayContract(type);
}
//...
else
{
JsonObjectContract jsonObjectContract = contract as JsonObjectContract;
if (jsonObjectContract != null)
{
newContract = CloneJsonObjectContract(new JsonObjectContract(type), jsonObjectContract);
}
else
{
throw new ArgumentException("Unknown JsonContract type: " + contract.GetType() + ", object: " + contract);
}
}
//Copy properties like IsReference, OnSerializingCallbacks etc. and set the new converter
return newContract;
}
static JsonObjectContract CloneJsonObjectContract(JsonObjectContract newContract, JsonObjectContract oldContract)
{
newContract.OverrideCreator = oldContract.OverrideCreator;
newContract.DefaultCreator = oldContract.DefaultCreator;
newContract.DefaultCreatorNonPublic = oldContract.DefaultCreatorNonPublic;
newContract.ParametrizedConstructor = oldContract.ParametrizedConstructor; // If I do no copy this then the behavior of the old and new contract is different.
CloneJsonPropertyList(newContract.Properties, oldContract.Properties);
CloneJsonPropertyList(newContract.CreatorParameters, oldContract.CreatorParameters);
return newContract;
}
}