Пример #1
0
 /// <summary>
 ///   Gets the value associated with the specified property name.
 /// </summary>
 /// <param name="propertyName">The property name of the value to get.</param>
 /// <param name="jsonNode">
 ///   When this method returns, contains the value associated with the specified property name, if the property name is found;
 ///   otherwise, <see langword="null"/>.
 /// </param>
 /// <returns>
 ///   <see langword="true"/> if the <see cref="JsonObject"/> contains an element with the specified property name; otherwise, <see langword="false"/>.
 /// </returns>
 /// <exception cref="ArgumentNullException">
 ///   <paramref name="propertyName"/> is <see langword="null"/>.
 /// </exception>
 bool IDictionary <string, JsonNode?> .TryGetValue(string propertyName, out JsonNode?jsonNode)
 {
     InitializeIfRequired();
     Debug.Assert(_dictionary != null);
     return(_dictionary.TryGetValue(propertyName, out jsonNode));
 }
Пример #2
0
        internal JsonParameterInfo?GetParameter(
            ReadOnlySpan <byte> propertyName,
            ref ReadStackFrame frame,
            out byte[] utf8PropertyName)
        {
            ParameterRef parameterRef;

            ulong key = GetKey(propertyName);

            // Keep a local copy of the cache in case it changes by another thread.
            ParameterRef[]? localParameterRefsSorted = _parameterRefsSorted;

            // If there is an existing cache, then use it.
            if (localParameterRefsSorted != null)
            {
                // Start with the current parameter index, and then go forwards\backwards.
                int parameterIndex = frame.CtorArgumentState !.ParameterIndex;

                int count     = localParameterRefsSorted.Length;
                int iForward  = Math.Min(parameterIndex, count);
                int iBackward = iForward - 1;

                while (true)
                {
                    if (iForward < count)
                    {
                        parameterRef = localParameterRefsSorted[iForward];
                        if (IsParameterRefEqual(parameterRef, propertyName, key))
                        {
                            utf8PropertyName = parameterRef.NameFromJson;
                            return(parameterRef.Info);
                        }

                        ++iForward;

                        if (iBackward >= 0)
                        {
                            parameterRef = localParameterRefsSorted[iBackward];
                            if (IsParameterRefEqual(parameterRef, propertyName, key))
                            {
                                utf8PropertyName = parameterRef.NameFromJson;
                                return(parameterRef.Info);
                            }

                            --iBackward;
                        }
                    }
                    else if (iBackward >= 0)
                    {
                        parameterRef = localParameterRefsSorted[iBackward];
                        if (IsParameterRefEqual(parameterRef, propertyName, key))
                        {
                            utf8PropertyName = parameterRef.NameFromJson;
                            return(parameterRef.Info);
                        }

                        --iBackward;
                    }
                    else
                    {
                        // Property was not found.
                        break;
                    }
                }
            }

            // No cached item was found. Try the main dictionary which has all of the parameters.
            Debug.Assert(ParameterCache != null);

            if (ParameterCache.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonParameterInfo? info))
            {
                Debug.Assert(info != null);

                if (Options.PropertyNameCaseInsensitive)
                {
                    if (propertyName.SequenceEqual(info.NameAsUtf8Bytes))
                    {
                        Debug.Assert(key == GetKey(info.NameAsUtf8Bytes.AsSpan()));

                        // Use the existing byte[] reference instead of creating another one.
                        utf8PropertyName = info.NameAsUtf8Bytes !;
                    }
                    else
                    {
                        // Make a copy of the original Span.
                        utf8PropertyName = propertyName.ToArray();
                    }
                }
                else
                {
                    Debug.Assert(key == GetKey(info.NameAsUtf8Bytes !.AsSpan()));
                    utf8PropertyName = info.NameAsUtf8Bytes !;
                }
            }
            else
            {
                Debug.Assert(info == null);

                // Make a copy of the original Span.
                utf8PropertyName = propertyName.ToArray();
            }

            // Check if we should add this to the cache.
            // Only cache up to a threshold length and then just use the dictionary when an item is not found in the cache.
            int cacheCount = 0;

            if (localParameterRefsSorted != null)
            {
                cacheCount = localParameterRefsSorted.Length;
            }

            // Do a quick check for the stable (after warm-up) case.
            if (cacheCount < ParameterNameCountCacheThreshold)
            {
                // Do a slower check for the warm-up case.
                if (frame.CtorArgumentState !.ParameterRefCache != null)
                {
                    cacheCount += frame.CtorArgumentState.ParameterRefCache.Count;
                }

                // Check again to append the cache up to the threshold.
                if (cacheCount < ParameterNameCountCacheThreshold)
                {
                    if (frame.CtorArgumentState.ParameterRefCache == null)
                    {
                        frame.CtorArgumentState.ParameterRefCache = new List <ParameterRef>();
                    }

                    parameterRef = new ParameterRef(key, info !, utf8PropertyName);
                    frame.CtorArgumentState.ParameterRefCache.Add(parameterRef);
                }
            }

            return(info);
        }