Example #1
0
        /// <summary>
        /// Creates serialization metadata for a collection.
        /// </summary>
        public JsonTypeInfoInternal(
            JsonSerializerOptions options,
            JsonCollectionInfoValues <T> collectionInfo,
            Func <JsonConverter <T> > converterCreator,
            object?createObjectWithArgs = null,
            object?addFunc = null)
            : base(typeof(T), options)
        {
            if (collectionInfo == null)
            {
                throw new ArgumentNullException(nameof(collectionInfo));
            }

            ConverterStrategy strategy  = collectionInfo.KeyInfo == null ? ConverterStrategy.Enumerable : ConverterStrategy.Dictionary;
            JsonConverter <T> converter = new JsonMetadataServicesConverter <T>(converterCreator, strategy);

            KeyType                 = converter.KeyType;
            ElementType             = converter.ElementType;
            KeyTypeInfo             = collectionInfo.KeyInfo;
            ElementTypeInfo         = collectionInfo.ElementInfo ?? throw new ArgumentNullException(nameof(collectionInfo.ElementInfo));
            NumberHandling          = collectionInfo.NumberHandling;
            PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options);
            SerializeHandler        = collectionInfo.SerializeHandler;
            CreateObjectWithArgs    = createObjectWithArgs;
            AddMethodDelegate       = addFunc;
            SetCreateObjectFunc(collectionInfo.ObjectCreator);
        }
Example #2
0
 public JsonMetadataServicesConverter(Func <JsonConverter <T> > converterCreator, ConverterStrategy converterStrategy, Type?keyType, Type?elementType)
 {
     _converterCreator  = converterCreator ?? throw new ArgumentNullException(nameof(converterCreator));
     _converterStrategy = converterStrategy;
     _keyType           = keyType;
     _elementType       = elementType;
 }
Example #3
0
        internal string GetDebugInfo()
        {
            ConverterStrategy strat       = PropertyInfoForTypeInfo.ConverterStrategy;
            string            jtiTypeName = GetType().Name;
            string            typeName    = Type.FullName !;
            bool propCacheInitialized     = PropertyCache != null;

            StringBuilder sb = new();

            sb.AppendLine("{");
            sb.AppendLine($"  GetType: {jtiTypeName},");
            sb.AppendLine($"  Type: {typeName},");
            sb.AppendLine($"  ConverterStrategy: {strat},");
            sb.AppendLine($"  IsConfigured: {_isConfigured},");
            sb.AppendLine($"  HasPropertyCache: {propCacheInitialized},");

            if (propCacheInitialized)
            {
                sb.AppendLine("  Properties: {");
                foreach (var property in PropertyCache !.List)
                {
                    JsonPropertyInfo pi = property.Value !;
                    sb.AppendLine($"    {property.Key}:");
                    sb.AppendLine($"{pi.GetDebugInfo(indent: 6)},");
                }

                sb.AppendLine("  },");
            }

            sb.AppendLine("}");
            return(sb.ToString());
        }
Example #4
0
 internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy)
 {
     Type    = type;
     Options = options ?? throw new ArgumentNullException(nameof(options));
     // Setting this option is deferred to the initialization methods of the various metadada info types.
     PropertyInfoForTypeInfo = null !;
 }
Example #5
0
 public NullableConverter(JsonConverter <T> elementConverter)
 {
     _elementConverter = elementConverter;
     ConverterStrategy = elementConverter.ConverterStrategy;
     IsInternalConverterForNumberType = elementConverter.IsInternalConverterForNumberType;
     // temporary workaround for JsonConverter base constructor needing to access
     // ConverterStrategy when calculating `CanUseDirectReadOrWrite`.
     CanUseDirectReadOrWrite = elementConverter.ConverterStrategy == ConverterStrategy.Value;
 }
Example #6
0
 internal abstract void Initialize(
     Type parentClassType,
     Type declaredPropertyType,
     ConverterStrategy converterStrategy,
     MemberInfo?memberInfo,
     bool isVirtual,
     JsonConverter converter,
     JsonIgnoreCondition?ignoreCondition,
     JsonSerializerOptions options,
     JsonTypeInfo?jsonTypeInfo = null);
        public JsonMetadataServicesConverter(Func<JsonConverter<T>> converterCreator, ConverterStrategy converterStrategy)
        {
            if (converterCreator is null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(converterCreator));
            }

            _converterCreator = converterCreator;
            _converterStrategy = converterStrategy;
        }
Example #8
0
        internal static bool SingleValueReadWithReadAhead(ConverterStrategy converterStrategy, ref Utf8JsonReader reader, ref ReadStack state)
        {
            bool readAhead = state.ReadAhead && converterStrategy == ConverterStrategy.Value;

            if (!readAhead)
            {
                return(reader.Read());
            }

            return(DoSingleValueReadWithReadAhead(ref reader, ref state));
        }
Example #9
0
        public NullableConverter(JsonConverter <T> elementConverter)
        {
            _elementConverter = elementConverter;
            IsInternalConverterForNumberType = elementConverter.IsInternalConverterForNumberType;

            // Workaround for the base constructor depending on the (still unset) ConverterStrategy
            // to derive the CanUseDirectReadOrWrite and RequiresReadAhead values.
            ConverterStrategy       = elementConverter.ConverterStrategy;
            CanUseDirectReadOrWrite = elementConverter.CanUseDirectReadOrWrite;
            RequiresReadAhead       = elementConverter.RequiresReadAhead;
        }
Example #10
0
        public FSharpValueOptionConverter(JsonConverter <TElement> elementConverter)
        {
            _elementConverter  = elementConverter;
            _optionValueGetter = FSharpCoreReflectionProxy.Instance.CreateFSharpValueOptionValueGetter <TValueOption, TElement>();
            _optionConstructor = FSharpCoreReflectionProxy.Instance.CreateFSharpValueOptionSomeConstructor <TValueOption, TElement>();

            // Workaround for the base constructor depending on the (still unset) ConverterStrategy
            // to derive the CanUseDirectReadOrWrite and RequiresReadAhead values.
            _converterStrategy      = elementConverter.ConverterStrategy;
            CanUseDirectReadOrWrite = elementConverter.CanUseDirectReadOrWrite;
            RequiresReadAhead       = elementConverter.RequiresReadAhead;
        }
Example #11
0
        public FSharpValueOptionConverter(JsonConverter <TElement> elementConverter)
        {
            _elementConverter  = elementConverter;
            _optionValueGetter = FSharpCoreReflectionProxy.Instance.CreateFSharpValueOptionValueGetter <TValueOption, TElement>();
            _optionConstructor = FSharpCoreReflectionProxy.Instance.CreateFSharpValueOptionSomeConstructor <TValueOption, TElement>();

            // temporary workaround for JsonConverter base constructor needing to access
            // ConverterStrategy when calculating `CanUseDirectReadOrWrite`.
            // TODO move `CanUseDirectReadOrWrite` from JsonConverter to JsonTypeInfo.
            _converterStrategy      = _elementConverter.ConverterStrategy;
            CanUseDirectReadOrWrite = _converterStrategy == ConverterStrategy.Value;
        }
Example #12
0
        public void Push()
        {
            if (_continuationCount == 0)
            {
                if (_count == 0)
                {
                    // Performance optimization: reuse the first stackframe on the first push operation.
                    // NB need to be careful when making writes to Current _before_ the first `Push`
                    // operation is performed.
                    _count = 1;
                }
                else
                {
                    JsonTypeInfo       jsonTypeInfo      = Current.JsonPropertyInfo?.JsonTypeInfo ?? Current.CtorArgumentState !.JsonParameterInfo !.JsonTypeInfo;
                    JsonNumberHandling?numberHandling    = Current.NumberHandling;
                    ConverterStrategy  converterStrategy = Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterStrategy;

                    EnsurePushCapacity();
                    _stack[_count - 1] = Current;
                    Current            = default;
                    _count++;

                    Current.JsonTypeInfo     = jsonTypeInfo;
                    Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo;
                    // Allow number handling on property to win over handling on type.
                    Current.NumberHandling = numberHandling ?? Current.JsonPropertyInfo.NumberHandling;
                }
            }
            else
            {
                // We are re-entering a continuation, adjust indices accordingly
                if (_count++ > 0)
                {
                    _stack[_count - 2] = Current;
                    Current            = _stack[_count - 1];
                }

                // check if we are done
                if (_continuationCount == _count)
                {
                    _continuationCount = 0;
                }
            }

            SetConstructorArgumentState();
#if DEBUG
            // Ensure the method is always exercised in debug builds.
            _ = JsonPath();
#endif
        }
Example #13
0
        internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy)
        {
            // Options setting for object class types is deferred till initialization.
            if (converterStrategy != ConverterStrategy.Object && options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            Options = options !;
            Type    = type;

            // Setting this option is deferred to the initialization methods of the various metadada info types.
            PropertyInfoForTypeInfo = null !;
        }
Example #14
0
        internal virtual void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            ConverterStrategy converterStrategy,
            MemberInfo?memberInfo,
            bool isVirtual,
            JsonConverter converter,
            JsonIgnoreCondition?ignoreCondition,
            JsonNumberHandling?parentTypeNumberHandling,
            JsonSerializerOptions options)
        {
            Debug.Assert(converter != null);

            DeclaringType     = parentClassType;
            PropertyType      = declaredPropertyType;
            ConverterStrategy = converterStrategy;
            MemberInfo        = memberInfo;
            IsVirtual         = isVirtual;
            ConverterBase     = converter;
            Options           = options;
        }
Example #15
0
        internal virtual void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            Type?runtimePropertyType,
            ConverterStrategy runtimeClassType,
            MemberInfo?memberInfo,
            JsonConverter converter,
            JsonIgnoreCondition?ignoreCondition,
            JsonNumberHandling?parentTypeNumberHandling,
            JsonSerializerOptions options)
        {
            Debug.Assert(converter != null);

            ClrName              = memberInfo?.Name;
            DeclaringType        = parentClassType;
            DeclaredPropertyType = declaredPropertyType;
            RuntimePropertyType  = runtimePropertyType;
            ConverterStrategy    = runtimeClassType;
            MemberInfo           = memberInfo;
            ConverterBase        = converter;
            Options              = options;
        }
Example #16
0
        public void Push()
        {
            if (_continuationCount == 0)
            {
                if (_count == 0)
                {
                    // The first stack frame is held in Current.
                    _count = 1;
                }
                else
                {
                    JsonTypeInfo       jsonTypeInfo;
                    JsonNumberHandling?numberHandling    = Current.NumberHandling;
                    ConverterStrategy  converterStrategy = Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterStrategy;

                    if (converterStrategy == ConverterStrategy.Object)
                    {
                        if (Current.JsonPropertyInfo != null)
                        {
                            jsonTypeInfo = Current.JsonPropertyInfo.RuntimeTypeInfo;
                        }
                        else
                        {
                            jsonTypeInfo = Current.CtorArgumentState !.JsonParameterInfo !.RuntimeTypeInfo;
                        }
                    }
                    else if (converterStrategy == ConverterStrategy.Value)
                    {
                        // Although ConverterStrategy.Value doesn't push, a custom custom converter may re-enter serialization.
                        jsonTypeInfo = Current.JsonPropertyInfo !.RuntimeTypeInfo;
                    }
                    else
                    {
                        Debug.Assert(((ConverterStrategy.Enumerable | ConverterStrategy.Dictionary) & converterStrategy) != 0);
                        jsonTypeInfo = Current.JsonTypeInfo.ElementTypeInfo !;
                    }

                    AddCurrent();
                    Current.Reset();

                    Current.JsonTypeInfo     = jsonTypeInfo;
                    Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo;
                    // Allow number handling on property to win over handling on type.
                    Current.NumberHandling = numberHandling ?? Current.JsonPropertyInfo.NumberHandling;
                }
            }
            else if (_continuationCount == 1)
            {
                // No need for a push since there is only one stack frame.
                Debug.Assert(_count == 1);
                _continuationCount = 0;
            }
            else
            {
                // A continuation; adjust the index.
                Current = _previous[_count - 1];

                // Check if we are done.
                if (_count == _continuationCount)
                {
                    _continuationCount = 0;
                }
                else
                {
                    _count++;
                }
            }

            SetConstructorArgumentState();
        }
 public JsonMetadataServicesConverter(Func <JsonConverter <T> > converterCreator, ConverterStrategy converterStrategy)
 {
     _converterCreator  = converterCreator ?? throw new ArgumentNullException(nameof(converterCreator));
     _converterStrategy = converterStrategy;
 }
Example #18
0
 internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy) :
     base(type, options, converterStrategy)
 {
 }
Example #19
0
        public void Push()
        {
            if (_continuationCount == 0)
            {
                if (_count == 0)
                {
                    // The first stack frame is held in Current.
                    _count = 1;
                }
                else
                {
                    JsonTypeInfo       jsonTypeInfo;
                    JsonNumberHandling?numberHandling    = Current.NumberHandling;
                    ConverterStrategy  converterStrategy = Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterStrategy;

                    if (converterStrategy == ConverterStrategy.Object)
                    {
                        if (Current.JsonPropertyInfo != null)
                        {
                            jsonTypeInfo = Current.JsonPropertyInfo.RuntimeTypeInfo;
                        }
                        else
                        {
                            jsonTypeInfo = Current.CtorArgumentState !.JsonParameterInfo !.RuntimeTypeInfo;
                        }
                    }
                    else if (converterStrategy == ConverterStrategy.Value)
                    {
                        // Although ConverterStrategy.Value doesn't push, a custom custom converter may re-enter serialization.
                        jsonTypeInfo = Current.JsonPropertyInfo !.RuntimeTypeInfo;
                    }
                    else
                    {
                        Debug.Assert(((ConverterStrategy.Enumerable | ConverterStrategy.Dictionary) & converterStrategy) != 0);
                        jsonTypeInfo = Current.JsonTypeInfo.ElementTypeInfo !;
                    }

                    EnsurePushCapacity();
                    _stack[_count - 1] = Current;
                    Current            = default;
                    _count++;

                    Current.JsonTypeInfo     = jsonTypeInfo;
                    Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo;
                    // Allow number handling on property to win over handling on type.
                    Current.NumberHandling = numberHandling ?? Current.JsonPropertyInfo.NumberHandling;
                }
            }
            else
            {
                // We are re-entering a continuation, adjust indices accordingly
                if (_count++ > 0)
                {
                    Current = _stack[_count - 1];
                }

                // check if we are done
                if (_continuationCount == _count)
                {
                    _continuationCount = 0;
                }
            }

            SetConstructorArgumentState();
#if DEBUG
            // Ensure the method is always exercised in debug builds.
            _ = JsonPath();
#endif
        }
Example #20
0
        internal override void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            Type?runtimePropertyType,
            ConverterStrategy runtimeClassType,
            MemberInfo?memberInfo,
            bool isVirtual,
            JsonConverter converter,
            JsonIgnoreCondition?ignoreCondition,
            JsonNumberHandling?parentTypeNumberHandling,
            JsonSerializerOptions options)
        {
            base.Initialize(
                parentClassType,
                declaredPropertyType,
                runtimePropertyType,
                runtimeClassType,
                memberInfo,
                isVirtual,
                converter,
                ignoreCondition,
                parentTypeNumberHandling,
                options);

            switch (memberInfo)
            {
            case PropertyInfo propertyInfo:
            {
                bool useNonPublicAccessors = GetAttribute <JsonIncludeAttribute>(propertyInfo) != null;

                MethodInfo?getMethod = propertyInfo.GetMethod;
                if (getMethod != null && (getMethod.IsPublic || useNonPublicAccessors))
                {
                    HasGetter = true;
                    Get       = options.MemberAccessorStrategy.CreatePropertyGetter <T>(propertyInfo);
                }

                MethodInfo?setMethod = propertyInfo.SetMethod;
                if (setMethod != null && (setMethod.IsPublic || useNonPublicAccessors))
                {
                    HasSetter = true;
                    Set       = options.MemberAccessorStrategy.CreatePropertySetter <T>(propertyInfo);
                }

                MemberType = MemberTypes.Property;

                break;
            }

            case FieldInfo fieldInfo:
            {
                Debug.Assert(fieldInfo.IsPublic);

                HasGetter = true;
                Get       = options.MemberAccessorStrategy.CreateFieldGetter <T>(fieldInfo);

                if (!fieldInfo.IsInitOnly)
                {
                    HasSetter = true;
                    Set       = options.MemberAccessorStrategy.CreateFieldSetter <T>(fieldInfo);
                }

                MemberType = MemberTypes.Field;

                break;
            }

            default:
            {
                IsForTypeInfo = true;
                HasGetter     = true;
                HasSetter     = true;

                break;
            }
            }

            _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && DeclaredPropertyType != converter.TypeToConvert;
            PropertyTypeCanBeNull            = DeclaredPropertyType.CanBeNull();
            _propertyTypeEqualsTypeToConvert = typeof(T) == DeclaredPropertyType;

            GetPolicies(ignoreCondition, parentTypeNumberHandling);
        }
Example #21
0
        private static JsonConverter GetConverter(JsonCollectionInfoValues <T> collectionInfo, Func <JsonConverter <T> > converterCreator)
        {
            ConverterStrategy strategy = collectionInfo.KeyInfo == null ? ConverterStrategy.Enumerable : ConverterStrategy.Dictionary;

            return(new JsonMetadataServicesConverter <T>(converterCreator, strategy));
        }
Example #22
0
 private bool UseConverterStrategy(ConverterStrategy strategy) {
     return (this.converterStrategy & strategy) == strategy;
 }
 public JsonMetadataServicesConverter(JsonConverter<T> converter)
 {
     _converter = converter;
     _converterStrategy = converter.ConverterStrategy;
 }
Example #24
0
 /// <summary>
 /// Creates serialization metadata given JsonSerializerOptions and a ConverterStrategy.
 /// </summary>
 public JsonTypeInfoInternal(JsonSerializerOptions options, ConverterStrategy converterStrategy)
     : base(typeof(T), options, converterStrategy)
 {
 }
Example #25
0
        internal override void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            ConverterStrategy converterStrategy,
            MemberInfo?memberInfo,
            bool isVirtual,
            JsonConverter converter,
            JsonIgnoreCondition?ignoreCondition,
            JsonSerializerOptions options,
            JsonTypeInfo?jsonTypeInfo = null)
        {
            Debug.Assert(converter != null);

            PropertyType      = declaredPropertyType;
            ConverterStrategy = converterStrategy;
            if (jsonTypeInfo != null)
            {
                JsonTypeInfo = jsonTypeInfo;
            }

            ConverterBase   = converter;
            Options         = options;
            DeclaringType   = parentClassType;
            MemberInfo      = memberInfo;
            IsVirtual       = isVirtual;
            IgnoreCondition = ignoreCondition;

            if (memberInfo != null)
            {
                switch (memberInfo)
                {
                case PropertyInfo propertyInfo:
                {
                    bool useNonPublicAccessors = GetAttribute <JsonIncludeAttribute>(propertyInfo) != null;

                    MethodInfo?getMethod = propertyInfo.GetMethod;
                    if (getMethod != null && (getMethod.IsPublic || useNonPublicAccessors))
                    {
                        HasGetter = true;
                        Get       = options.MemberAccessorStrategy.CreatePropertyGetter <T>(propertyInfo);
                    }

                    MethodInfo?setMethod = propertyInfo.SetMethod;
                    if (setMethod != null && (setMethod.IsPublic || useNonPublicAccessors))
                    {
                        HasSetter = true;
                        Set       = options.MemberAccessorStrategy.CreatePropertySetter <T>(propertyInfo);
                    }

                    MemberType = MemberTypes.Property;

                    break;
                }

                case FieldInfo fieldInfo:
                {
                    Debug.Assert(fieldInfo.IsPublic);

                    HasGetter = true;
                    Get       = options.MemberAccessorStrategy.CreateFieldGetter <T>(fieldInfo);

                    if (!fieldInfo.IsInitOnly)
                    {
                        HasSetter = true;
                        Set       = options.MemberAccessorStrategy.CreateFieldSetter <T>(fieldInfo);
                    }

                    MemberType = MemberTypes.Field;

                    break;
                }

                default:
                {
                    Debug.Fail($"Invalid memberInfo type: {memberInfo.GetType().FullName}");
                    break;
                }
                }

                GetPolicies();
            }
            else
            {
                IsForTypeInfo = true;
                HasGetter     = true;
                HasSetter     = true;
            }
        }