Ejemplo n.º 1
0
 /// <summary>
 ///   Adds an element with the provided property name and value to the <see cref="JsonObject"/>.
 /// </summary>
 /// <param name="propertyName">The property name of the element to add.</param>
 /// <param name="value">The value of the element to add.</param>
 /// <exception cref="ArgumentNullException">
 ///   <paramref name="propertyName"/>is <see langword="null"/>.
 /// </exception>
 /// <exception cref="ArgumentException">
 ///   An element with the same property name already exists in the <see cref="JsonObject"/>.
 /// </exception>
 public void Add(string propertyName, JsonNode?value)
 {
     InitializeIfRequired();
     Debug.Assert(_dictionary != null);
     _dictionary.Add(propertyName, value);
     value?.AssignParent(this);
 }
Ejemplo n.º 2
0
        private void InitializeIfRequired()
        {
            if (_dictionary != null)
            {
                return;
            }

            bool caseInsensitive = Options.HasValue ? Options.Value.PropertyNameCaseInsensitive : false;
            var  dictionary      = new JsonPropertyDictionary <JsonNode>(caseInsensitive);

            if (_jsonElement.HasValue)
            {
                JsonElement jElement = _jsonElement.Value;

                foreach (JsonProperty jElementProperty in jElement.EnumerateObject())
                {
                    JsonNode?node = JsonNodeConverter.Create(jElementProperty.Value, Options);
                    if (node != null)
                    {
                        node.Parent = this;
                    }

                    dictionary.Add(new KeyValuePair <string, JsonNode?>(jElementProperty.Name, node));
                }

                _jsonElement = null;
            }

            _dictionary = dictionary;
        }
Ejemplo n.º 3
0
        internal void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters, bool sourceGenMode = false)
        {
            var parameterCache = new JsonPropertyDictionary <JsonParameterInfo>(Options.PropertyNameCaseInsensitive, jsonParameters.Length);

            // Cache the lookup from object property name to JsonPropertyInfo using a case-insensitive comparer.
            // Case-insensitive is used to support both camel-cased parameter names and exact matches when C#
            // record types or anonymous types are used.
            // The property name key does not use [JsonPropertyName] or PropertyNamingPolicy since we only bind
            // the parameter name to the object property name and do not use the JSON version of the name here.
            var nameLookup = new Dictionary <ParameterLookupKey, ParameterLookupValue>(PropertyCache !.Count);

            foreach (KeyValuePair <string, JsonPropertyInfo?> kvp in PropertyCache.List)
            {
                JsonPropertyInfo jsonProperty = kvp.Value !;
                string           propertyName = jsonProperty.ClrName !;

                ParameterLookupKey   key   = new(propertyName, jsonProperty.PropertyType);
                ParameterLookupValue value = new(jsonProperty);

                if (!JsonHelpers.TryAdd(nameLookup, key, value))
                {
                    // More than one property has the same case-insensitive name and Type.
                    // Remember so we can throw a nice exception if this property is used as a parameter name.
                    ParameterLookupValue existing = nameLookup[key];
                    existing.DuplicateName = propertyName;
                }
            }

            foreach (JsonParameterInfoValues parameterInfo in jsonParameters)
            {
                ParameterLookupKey paramToCheck = new(parameterInfo.Name, parameterInfo.ParameterType);

                if (nameLookup.TryGetValue(paramToCheck, out ParameterLookupValue? matchingEntry))
                {
                    if (matchingEntry.DuplicateName != null)
                    {
                        // Multiple object properties cannot bind to the same constructor parameter.
                        ThrowHelper.ThrowInvalidOperationException_MultiplePropertiesBindToConstructorParameters(
                            Type,
                            parameterInfo.Name !,
                            matchingEntry.JsonPropertyInfo.Name,
                            matchingEntry.DuplicateName);
                    }

                    Debug.Assert(matchingEntry.JsonPropertyInfo != null);
                    JsonPropertyInfo  jsonPropertyInfo  = matchingEntry.JsonPropertyInfo;
                    JsonParameterInfo jsonParameterInfo = CreateConstructorParameter(parameterInfo, jsonPropertyInfo, sourceGenMode, Options);
                    parameterCache.Add(jsonPropertyInfo.Name, jsonParameterInfo);
                }
                // It is invalid for the extension data property to bind with a constructor argument.
                else if (DataExtensionProperty != null &&
                         StringComparer.OrdinalIgnoreCase.Equals(paramToCheck.Name, DataExtensionProperty.Name))
                {
                    ThrowHelper.ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(DataExtensionProperty);
                }
            }

            ParameterCount = jsonParameters.Length;
            Volatile.Write(ref ParameterCache, parameterCache);
        }