Esempio n. 1
0
        /// <summary>
        /// Asynchronously writes an instance annotation.
        /// </summary>
        /// <param name="instanceAnnotation">The instance annotation to write.</param>
        /// <param name="ignoreFilter">Whether to ignore the filter in settings.</param>
        /// <param name="propertyName">The name of the property this instance annotation applies tos</param>
        internal async Task WriteInstanceAnnotationAsync(
            ODataInstanceAnnotation instanceAnnotation,
            bool ignoreFilter   = false,
            string propertyName = null)
        {
            string     annotationName  = instanceAnnotation.Name;
            ODataValue annotationValue = instanceAnnotation.Value;

            Debug.Assert(!string.IsNullOrEmpty(annotationName), "annotationName should not be null or empty");
            Debug.Assert(annotationValue != null, "annotationValue should not be null because we use ODataNullValue for null instead");
            Debug.Assert(!(annotationValue is ODataStreamReferenceValue), "!(annotationValue 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 (!ignoreFilter && this.valueSerializer.MessageWriterSettings.ShouldSkipAnnotation(annotationName))
            {
                return;
            }

            IEdmTypeReference expectedType = MetadataUtils.LookupTypeOfTerm(annotationName, this.valueSerializer.Model);

            if (annotationValue is ODataNullValue)
            {
                if (expectedType != null && !expectedType.IsNullable)
                {
                    throw new ODataException(
                              ODataErrorStrings.JsonLightInstanceAnnotationWriter_NullValueNotAllowedForInstanceAnnotation(
                                  annotationName, expectedType.FullName()));
                }

                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteNullValueAsync()
                .ConfigureAwait(false);

                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;

            ODataResourceValue resourceValue = annotationValue as ODataResourceValue;

            if (resourceValue != null)
            {
                IDuplicatePropertyNameChecker duplicatePropertyNameChecker = this.valueSerializer.GetDuplicatePropertyNameChecker();
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteResourceValueAsync(resourceValue,
                                                                   expectedType,
                                                                   treatLikeOpenProperty,
                                                                   duplicatePropertyNameChecker).ConfigureAwait(false);

                this.valueSerializer.ReturnDuplicatePropertyNameChecker(duplicatePropertyNameChecker);

                return;
            }

            ODataCollectionValue collectionValue = annotationValue as ODataCollectionValue;

            if (collectionValue != null)
            {
                IEdmTypeReference typeFromCollectionValue = (IEdmCollectionTypeReference)TypeNameOracle.ResolveAndValidateTypeForCollectionValue(
                    this.valueSerializer.Model, expectedType, collectionValue, treatLikeOpenProperty, this.writerValidator);
                string collectionTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(collectionValue, expectedType, typeFromCollectionValue, treatLikeOpenProperty);
                if (collectionTypeNameToWrite != null)
                {
                    await this.asynchronousODataAnnotationWriter.WriteODataTypePropertyAnnotationAsync(annotationName, collectionTypeNameToWrite)
                    .ConfigureAwait(false);
                }

                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteCollectionValueAsync(
                    collectionValue,
                    expectedType,
                    typeFromCollectionValue,
                    false /*isTopLevelProperty*/,
                    false /*isInUri*/,
                    treatLikeOpenProperty).ConfigureAwait(false);

                return;
            }

            ODataUntypedValue untypedValue = annotationValue as ODataUntypedValue;

            if (untypedValue != null)
            {
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteUntypedValueAsync(untypedValue)
                .ConfigureAwait(false);

                return;
            }

            ODataEnumValue enumValue = annotationValue as ODataEnumValue;

            if (enumValue != null)
            {
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteEnumValueAsync(enumValue, expectedType)
                .ConfigureAwait(false);

                return;
            }

            ODataPrimitiveValue primitiveValue = annotationValue as ODataPrimitiveValue;

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

            IEdmTypeReference typeFromPrimitiveValue = TypeNameOracle.ResolveAndValidateTypeForPrimitiveValue(primitiveValue);

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

            if (primitiveTypeNameToWrite != null)
            {
                await this.asynchronousODataAnnotationWriter.WriteODataTypePropertyAnnotationAsync(annotationName, primitiveTypeNameToWrite)
                .ConfigureAwait(false);
            }

            await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
            .ConfigureAwait(false);

            await this.valueSerializer.WritePrimitiveValueAsync(primitiveValue.Value, typeFromPrimitiveValue, expectedType)
            .ConfigureAwait(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the type name based on the given odata value.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="model">The model used to handle unsigned int conversions.</param>
        /// <returns>The type name for the context URI.</returns>
        private static string GetTypeNameForValue(ODataValue value, IEdmModel model)
        {
            if (value == null)
            {
                return(null);
            }

            // special identifier for null values.
            if (value.IsNullValue)
            {
                return(ODataConstants.ContextUriFragmentNull);
            }

            if (value.TypeAnnotation != null && !string.IsNullOrEmpty(value.TypeAnnotation.TypeName))
            {
                return(value.TypeAnnotation.TypeName);
            }

            var collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName));
            }

            var enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(enumValue.TypeName);
            }

            var resourceValue = value as ODataResourceValue;

            if (resourceValue != null)
            {
                return(resourceValue.TypeName);
            }

            var untypedValue = value as ODataUntypedValue;

            if (untypedValue != null)
            {
                return(ODataConstants.ContextUriFragmentUntyped);
            }

            ODataPrimitiveValue primitive = value as ODataPrimitiveValue;

            if (primitive == null)
            {
                Debug.Assert(value is ODataStreamReferenceValue, "value is ODataStreamReferenceValue");
                throw new ODataException(Strings.ODataContextUriBuilder_StreamValueMustBePropertiesOfODataResource);
            }

            // Try convert to underlying type if the primitive value is unsigned int.
            IEdmTypeDefinitionReference typeDefinitionReference = model.ResolveUIntTypeDefinition(primitive.Value);

            if (typeDefinitionReference != null)
            {
                return(typeDefinitionReference.FullName());
            }

            IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitive.Value.GetType());

            return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.FullName());
        }
 /// <summary>
 /// Constructs a new <see cref="ODataInstanceAnnotation"/> instance.
 /// </summary>
 /// <param name="name">The name of the instance annotation.</param>
 /// <param name="value">The value of the instance annotation.</param>
 public ODataInstanceAnnotation(string name, ODataValue value)
     : this(name, value, false)
 {
 }