/// <summary>
        /// Writes an instance annotation.
        /// </summary>
        /// <param name="instanceAnnotation">The instance annotation to write.</param>
        internal void WriteInstanceAnnotation(ODataInstanceAnnotation instanceAnnotation)
        {
            DebugUtils.CheckNoExternalCallers();

            string     name  = instanceAnnotation.Name;
            ODataValue value = instanceAnnotation.Value;

            Debug.Assert(!string.IsNullOrEmpty(name), "name should not be null or empty");
            Debug.Assert(!ODataAnnotationNames.IsODataAnnotationName(name), "A reserved name cannot be used as instance annotation key");
            Debug.Assert(value != null, "value should not be null because we use ODataNullValue for null instead");
            Debug.Assert(!(value is ODataStreamReferenceValue), "!(value is ODataStreamReferenceValue) -- ODataInstanceAnnotation and InstanceAnnotationCollection will throw if the value is a stream value.");
            Debug.Assert(this.valueSerializer.Model != null, "this.valueSerializer.Model != null");

            if (this.valueSerializer.Settings.ShouldSkipAnnotation(name))
            {
                return;
            }

            IEdmTypeReference expectedType = MetadataUtils.LookupTypeOfValueTerm(name, this.valueSerializer.Model);

            if (value is ODataNullValue)
            {
                if (expectedType != null && !expectedType.IsNullable)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomPropertyAndValueSerializer_NullValueNotAllowedForInstanceAnnotation(instanceAnnotation.Name, expectedType.ODataFullName()));
                }

                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteNullValue();
                return;
            }

            // If we didn't find an expected type from looking up the term in the model, treat this value the same way we would for open property values.
            // That is, write the type name (unless its a primitive value with a JSON-native type).  If we did find an expected type, treat the annotation value like a
            // declared property with an expected type. This will still write out the type if the value type is more derived than the declared type, for example.
            bool treatLikeOpenProperty = expectedType == null;

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteComplexValue(complexValue, expectedType, false /*isTopLevel*/, treatLikeOpenProperty, this.valueSerializer.CreateDuplicatePropertyNamesChecker());
                return;
            }

            IEdmTypeReference    typeFromValue   = TypeNameOracle.ResolveAndValidateTypeNameForValue(this.valueSerializer.Model, expectedType, value, treatLikeOpenProperty);
            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                string collectionTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(collectionValue, expectedType, typeFromValue, treatLikeOpenProperty);
                if (collectionTypeNameToWrite != null)
                {
                    ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, collectionTypeNameToWrite);
                }

                this.JsonWriter.WriteName(name);
                this.valueSerializer.WriteCollectionValue(collectionValue, expectedType, false /*isTopLevelProperty*/, false /*isInUri*/, treatLikeOpenProperty);
                return;
            }

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            Debug.Assert(primitiveValue != null, "Did we add a new subclass of ODataValue?");

            string primitiveTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(primitiveValue, expectedType, typeFromValue, treatLikeOpenProperty);

            if (primitiveTypeNameToWrite != null)
            {
                ODataJsonLightWriterUtils.WriteODataTypePropertyAnnotation(this.JsonWriter, name, primitiveTypeNameToWrite);
            }

            this.JsonWriter.WriteName(name);
            this.valueSerializer.WritePrimitiveValue(primitiveValue.Value, expectedType);
        }
示例#2
0
        /// <summary>
        /// Resolves and validates the Edm type for the given <paramref name="value"/>.
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="value">The value in question to resolve the type for.</param>
        /// <param name="isOpenProperty">true if the type name belongs to an open property, false otherwise.</param>
        /// <returns>A type for the <paramref name="value"/> or null if no metadata is available.</returns>
        internal static IEdmTypeReference ResolveAndValidateTypeNameForValue(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata, ODataValue value, bool isOpenProperty)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(model != null, "model != null");
            Debug.Assert(value != null, "value != null");

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            if (primitiveValue != null)
            {
                Debug.Assert(primitiveValue.Value != null, "primitiveValue.Value != null");
                return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()));
            }

            ODataComplexValue complexValue = value as ODataComplexValue;

            if (complexValue != null)
            {
                return(ResolveAndValidateTypeFromNameAndMetadata(model, typeReferenceFromMetadata, complexValue.TypeName, EdmTypeKind.Complex, isOpenProperty));
            }

            ODataCollectionValue collectionValue = (ODataCollectionValue)value;

            return(ResolveAndValidateTypeFromNameAndMetadata(model, typeReferenceFromMetadata, collectionValue.TypeName, EdmTypeKind.Collection, isOpenProperty));
        }