public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var token = JToken.Load(reader);

            var paramType = objectType.GenericTypeArguments[0];

            // handle tuples
            // handle objects with Probability property (by structural matching) (including wrapper on tuple)
            if (ValueTupleReflectionHelper.IsValueTupleOrNullableType(paramType) ||
                paramType.GetProperty(nameof(IProbabilityObject.Probability)) != null)
            {
                if (token is JArray jArray)
                {
                    Type arType;
                    if (paramType.GetInterface(nameof(IProbabilityObject)) != null)
                    {
                        arType = paramType.MakeArrayType();
                    }
                    else
                    {
                        arType = typeof(ProbabilityObjectWrapper <>).MakeGenericType(paramType).MakeArrayType();
                    }
                    var wrapperType = typeof(ProbabilityObjectCollection <>).MakeGenericType(paramType);
                    var parsedArray = jArray.ToObject(arType, serializer);
                    var wrapper     = Activator.CreateInstance(wrapperType, parsedArray);
                    return(wrapperType.GetProperty(nameof(ProbabilityObjectCollection <IProbabilityObject> .ProbabilityCollection)).GetValue(wrapper));
                }
            }

            if (token.Type == JTokenType.Null)
            {
                return(null);
            }

            //other (simple) cases
            switch (token)
            {
            case JObject jObject:
            {
                var dictType = typeof(IDictionary <,>).MakeGenericType(paramType, typeof(decimal?));
                return(Activator.CreateInstance(objectType, jObject.ToObject(dictType, serializer)));
            }

            case JArray jArray:
            {
                var arType = typeof(IList <>).MakeGenericType(paramType);
                return(Activator.CreateInstance(objectType, jArray.ToObject(arType, serializer)));
            }

            default:
                throw new InvalidOperationException("Invalid JToken type.");
            }
        }
 public override bool CanConvert(Type objectType) => ValueTupleReflectionHelper.IsValueTupleOrNullableType(objectType, out var _, out var _);