Exemplo n.º 1
0
        object CreateValueInternal(
            BitStreamReader reader,
            IContract contract,
            DsdlProperty member,
            ContainerContract containerContract,
            DsdlProperty containerMember,
            object existingValue,
            DsdlType scheme,
            Type objectType,
            bool tailArrayOptimization = false)
        {
            switch (scheme)
            {
            case VoidDsdlType t:
                ReadAlignment(reader, t);
                return(null);

            case PrimitiveDsdlType t:
                var primitive = ReadPrimitiveType(reader, t);
                return(EnsureType(reader, primitive, CultureInfo.InvariantCulture, contract, objectType));

            case ArrayDsdlType t when t.IsStringLike && contract.UnderlyingType == typeof(string):
                var list = CreateList(reader, StringContract, member, null, t, tailArrayOptimization) as IEnumerable <byte>;
                return(_encoding.GetString(list.ToArray()));

            case ArrayDsdlType t:
                return(CreateList(reader, contract, member, existingValue, t, tailArrayOptimization));

            case CompositeDsdlTypeBase t:
                return(CreateObject(reader, contract, member, containerContract, containerMember, existingValue, objectType, t, tailArrayOptimization));

            default:
                throw new ArgumentOutOfRangeException(nameof(scheme));
            }
        }
Exemplo n.º 2
0
        bool CalculatePropertyValues(object value, ContainerContract contract, DsdlProperty property, out IContract memberContract, out object memberValue)
        {
            memberContract = null;
            memberValue    = null;

            if (property.Ignored || !property.Readable)
            {
                return(false);
            }

            memberValue = property.ValueProvider.GetValue(value);
            if (memberValue == null)
            {
                return(false);
            }

            if (property.PropertyContract == null)
            {
                property.PropertyContract = _serializer.ContractResolver.ResolveContract(property.PropertyType);
            }

            memberContract = (property.PropertyContract.IsSealed) ?
                             property.PropertyContract :
                             _serializer.ContractResolver.ResolveContract(memberValue.GetType());

            if (!CheckForCircularReference(memberValue, property, memberContract))
            {
                return(false);
            }

            if (!CheckDsdlTypeCompatibility(property.DsdlType, memberContract))
            {
                throw new InvalidOperationException(
                          $"DSDL type mismatch for property '{contract.UnderlyingType.FullName}.{property.UnderlyingName}'.");
            }

            return(true);
        }
Exemplo n.º 3
0
        bool SetPropertyValue(
            DsdlProperty property,
            ContainerContract containerContract,
            DsdlProperty containerProperty,
            BitStreamReader reader,
            object target,
            DsdlType scheme,
            bool tailArrayOptimization)
        {
            if (property.Ignored)
            {
                return(true);
            }

            if (property.PropertyContract == null)
            {
                property.PropertyContract = GetContractSafe(property.PropertyType);
            }

            bool   useExistingValue = false;
            object currentValue     = null;

            if (property.Readable)
            {
                currentValue = property.ValueProvider.GetValue(target);
            }

            IContract propertyContract;

            if (currentValue == null)
            {
                propertyContract = property.PropertyContract;
            }
            else
            {
                propertyContract = GetContractSafe(currentValue.GetType());
                useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
            }

            var value = CreateValueInternal(
                reader,
                propertyContract,
                property,
                containerContract,
                containerProperty,
                (useExistingValue) ? currentValue : null,
                scheme,
                property.PropertyType,
                tailArrayOptimization);

            // always set the value if useExistingValue is false,
            // otherwise also set it if CreateValue returns a new value compared to the currentValue
            // this could happen because of a JsonConverter against the type
            if ((!useExistingValue || value != currentValue) &&
                ShouldSetPropertyValue(property, containerContract as ObjectContract, value))
            {
                property.ValueProvider.SetValue(target, value);

                return(true);
            }

            // the value wasn't set be JSON was populated onto the existing value
            return(useExistingValue);
        }
Exemplo n.º 4
0
        object CreateObject(
            BitStreamReader reader,
            IContract contract,
            DsdlProperty member,
            ContainerContract containerContract,
            DsdlProperty containerMember,
            object existingValue,
            Type objectType,
            CompositeDsdlTypeBase scheme,
            bool tailArrayOptimization)
        {
            if (HasNoDefinedType(contract))
            {
                return(CreateUnknownObject(reader, scheme));
            }

            switch (contract)
            {
            case ObjectContract objectContract:
            {
                bool   createdFromNonDefaultCreator = false;
                object targetObject;
                // check that if type name handling is being used that the existing value is compatible with the specified type
                if (existingValue != null && objectType != null && objectType.IsAssignableFrom(existingValue.GetType()))
                {
                    targetObject = existingValue;
                }
                else
                {
                    targetObject = CreateNewObject(reader, objectContract, member, containerMember, out createdFromNonDefaultCreator);
                }

                // don't populate if read from non-default creator because the object has already been read
                if (createdFromNonDefaultCreator)
                {
                    return(targetObject);
                }

                return(PopulateObject(targetObject, reader, objectContract, member, scheme, tailArrayOptimization));
            }

            case DictionaryContract dictionaryContract:
            {
                object targetDictionary;

                if (existingValue == null)
                {
                    var dictionary = CreateNewDictionary(reader, dictionaryContract, out bool createdFromNonDefaultCreator);

                    if (createdFromNonDefaultCreator && !dictionaryContract.HasParameterizedCreatorInternal)
                    {
                        throw new SerializationException("Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
                    }

                    PopulateDictionary(dictionary, reader, dictionaryContract, member, scheme, tailArrayOptimization);

                    if (createdFromNonDefaultCreator)
                    {
                        ObjectConstructor <object> creator = dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator;

                        return(creator(dictionary));
                    }
                    else if (dictionary is IWrappedDictionary wrappedDictionary)
                    {
                        return(wrappedDictionary.UnderlyingDictionary);
                    }

                    targetDictionary = dictionary;
                }
                else
                {
                    targetDictionary = PopulateDictionary(
                        dictionaryContract.ShouldCreateWrapper || !(existingValue is IDictionary) ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary)existingValue,
                        reader,
                        dictionaryContract,
                        member,
                        scheme,
                        tailArrayOptimization);
                }

                return(targetDictionary);
            }
            }

            throw new SerializationException($"Cannot deserialize the current object.");
        }
Exemplo n.º 5
0
        void SerializeObjectCore(
            BitStreamWriter writer,
            Func <string, ResolvedProperty?> propertyResolver,
            ContainerContract containerContract,
            DsdlType derivedDsdlType,
            bool tailArrayOptimization)
        {
            var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(containerContract, derivedDsdlType);

            //WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

            VoidDsdlType voidDsdlType      = null;
            int          voidDsdlTypeIndex = -1;
            var          isUnion           = dsdlScheme.IsUnion;
            var          unionMemberFound  = false;

            for (int i = 0; i < dsdlScheme.Fields.Count; i++)
            {
                var dsdlMember   = dsdlScheme.Fields[i];
                var isLastMember = i == dsdlScheme.Fields.Count - 1;

                if ((voidDsdlType = (dsdlMember.Type as VoidDsdlType)) != null)
                {
                    voidDsdlTypeIndex = i;
                    if (!isUnion)
                    {
                        WriteAlignment(writer, voidDsdlType);
                    }
                    continue;
                }

                var resolvedProp = propertyResolver(dsdlMember.Name);

                if (isUnion)
                {
                    if (resolvedProp == null)
                    {
                        continue;
                    }
                    if (unionMemberFound)
                    {
                        throw new InvalidOperationException($"Cannot find single union value for type '{containerContract.UnderlyingType.FullName}'.");
                    }
                    unionMemberFound = true;
                    WriteUnionFieldIndex(writer, i, dsdlScheme);
                    var rp = resolvedProp.Value;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type);
                }
                else
                {
                    if (resolvedProp == null)
                    {
                        throw new InvalidOperationException($"Cannot resove member '{containerContract.UnderlyingType.FullName}.{dsdlMember.Name}'.");
                    }
                    var rp  = resolvedProp.Value;
                    var tao = tailArrayOptimization &&
                              isLastMember &&
                              dsdlMember.Type is ArrayDsdlType adt;
                    SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type, tao);
                }
            }

            if (isUnion && !unionMemberFound)
            {
                if (voidDsdlType != null)
                {
                    WriteUnionFieldIndex(writer, voidDsdlTypeIndex, dsdlScheme);
                    WriteAlignment(writer, voidDsdlType);
                }
                else
                {
                    throw new InvalidOperationException($"Cannot find union value for '{containerContract.UnderlyingType.FullName}' type.");
                }
            }
        }