JsonObjectContract.ParametrizedConstructor
被标记为过时,并表示应该改用OverrideCreator
。但是OverrideCreator
没有设置_parametrizedConstructor
或_parameterizedCreator
这意味着如果您需要从外部设置这些值,则必须使用 ParametrizedConstructor
.
这是故意的吗?如果是这样,为什么?
谢谢!
编辑 1:
为了解释我为什么要问,我的应用程序中有一个处理序列化(使用 JSON.Net(的类。此类创建一个自定义IContractResolver
(基于 DefaultContractResolver
(,其中包含我为应用程序编写的一组常用JsonConverter
。这允许生成的协定检查一次转换器,然后进行缓存。
我的序列化类允许调用方传入自己的自定义转换器。完成此操作后,我将创建一个新IContractResolver
,该采用这些新转换器和默认合约解析器。然后,我要做的是,在解析某个类型的协定时,我首先从默认协定解析器获取协定。当我得到它时,我会检查并查看是否有任何新转换器可以处理该类型。如果可以的话,我可以"克隆"json合约并用新的转换器替换转换器(并缓存它(。
在此克隆中,我设置了ParametrizedConstructor
。我最初没有这样做,因为它被标记为已弃用,我只设置了OverrideCreator
.我在反序列化 Tuple
s 时遇到了一个问题。我一直收到一个错误,说元组没有构造函数。我尝试使用股票JsonConvert
来回Tuple
,效果很好。在研究为什么它适用于JsonConvert
时,我发现这是因为当我"克隆"合同时,我没有设置ParametrizedConstructor
。
编辑 2:
这是我的合约解析器的一个精简示例:
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;
}
}
两个属性 OverrideCreator
和 ParametrizedConstructor
(及其派生的委托属性 ParameterizedCreator
(的精确函数可以从 JsonSerializerInternalReader.CreateNewObject()
的参考源中看到:
-
如果有
OverrideCreator
,使用它使用CreatorParameters
创建对象。 -
否则,如果有一个
DefaultCreator
并且它是公共的或私有的,并且JsonSerializer.ConstructorHandling
说无论如何都要使用它,然后使用它来创建对象。 -
否则,如果有
ParameterizedCreator
,则使用它来创建对象。 -
否则无法构造对象,因此引发异常。
因此,OverrideCreator
无条件优先,而ParameterizedCreator
仅在没有DefaultCreator
时才用作回退。 我怀疑牛顿软件将后者标记为过时,因为他们想将其转换为internal
. 即,Json.NET 的用户将始终能够设置无条件覆盖创建者,但不需要设置条件回退创建器,根据ConstructorHandling
的值可能会或可能不会调用该创建器。
例如,如果要为特定类型的T
注入创建方法,则可以使用以下方法:
public class FactoryContractResolver<T> : DefaultContractResolver
{
readonly Func<T> creator;
public FactoryContractResolver(Func<T> creator)
{
this.creator = creator;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
if (objectType == typeof(T))
{
contract.OverrideCreator = delegate(object[] args) { return creator(); };
if (contract.CreatorParameters != null)
contract.CreatorParameters.Clear();
}
return contract;
}
}
请注意,如果找不到构造函数,基类DefaultContractResolver.CreateObjectContract
不会引发异常。 只有在反序列化期间实际尝试构造此类类型的实例时,才会引发异常。