JsonObjectContract.ParametrizedConstructor标记为过时,别无选择



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;
    } 
}

两个属性 OverrideCreatorParametrizedConstructor(及其派生的委托属性 ParameterizedCreator(的精确函数可以从 JsonSerializerInternalReader.CreateNewObject() 的参考源中看到:

  1. 如果有OverrideCreator,使用它使用CreatorParameters创建对象。

  2. 否则,如果有一个DefaultCreator并且它是公共的或私有的,并且JsonSerializer.ConstructorHandling说无论如何都要使用它,然后使用它来创建对象。

  3. 否则,如果有ParameterizedCreator,则使用它来创建对象。

  4. 否则无法构造对象,因此引发异常。

因此,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不会引发异常。 只有在反序列化期间实际尝试构造此类类型的实例时,才会引发异常。

相关内容

  • 没有找到相关文章

最新更新