/// <summary>
        /// Writes the metadata properties for a resource which can only occur at the start.
        /// </summary>
        /// <param name="resourceState">The resource state for which to write the metadata properties.</param>
        internal void WriteResourceStartMetadataProperties(IODataJsonLightWriterResourceState resourceState)
        {
            Debug.Assert(resourceState != null, "resourceState != null");

            ODataResourceBase resource = resourceState.Resource;

            // expectedResourceTypeName : if expected is of base type. but the resource real type is derived,
            // we need to set the resource type name.
            //      Writing response: expected type info can be identical with context uri info.
            //      Writing request: contextUri may not be provided, we always use the type from metadata info.
            //                       From model: if the resource can be found in model.
            //                       From serializationInfo: if user set the serializationInfo for the resource.
            string expectedResourceTypeName = null;

            if (this.WritingResponse)
            {
                expectedResourceTypeName = resourceState.GetOrCreateTypeContext(this.WritingResponse).ExpectedResourceTypeName;
            }
            else
            {
                if (resourceState.ResourceTypeFromMetadata == null)
                {
                    expectedResourceTypeName = resourceState.SerializationInfo == null
                     ? null
                     : resourceState.SerializationInfo.ExpectedTypeName;
                }
                else
                {
                    expectedResourceTypeName = resourceState.ResourceTypeFromMetadata.FullTypeName();
                }
            }

            // Write the "@odata.type": "typename"
            string typeName = this.JsonLightOutputContext.TypeNameOracle.GetResourceTypeNameForWriting(
                expectedResourceTypeName,
                resource,
                resourceState.IsUndeclared);

            if (typeName != null && !string.Equals(typeName, ODataConstants.ContextUriFragmentUntyped, StringComparison.Ordinal))
            {
                this.ODataAnnotationWriter.WriteODataTypeInstanceAnnotation(typeName);
            }

            // Write the "@odata.id": "Entity Id"
            Uri id;

            if (resource.MetadataBuilder.TryGetIdForSerialization(out id))
            {
                this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataId);
                if (id != null && !resource.HasNonComputedId)
                {
                    id = this.MetadataDocumentBaseUri.MakeRelativeUri(id);
                }

                this.JsonWriter.WriteValue(id == null ? null : this.UriToString(id));
            }

            // Write the "@odata.etag": "ETag value"
            string etag = resource.ETag;

            if (etag != null)
            {
                this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataETag);
                this.JsonWriter.WriteValue(etag);
            }
        }
        /// <summary>
        /// Writes the metadata properties for a resource which can only occur at the start.
        /// </summary>
        /// <param name="resourceState">The resource state for which to write the metadata properties.</param>
        internal void WriteResourceStartMetadataProperties(IODataJsonLightWriterResourceState resourceState)
        {
            Debug.Assert(resourceState != null, "resourceState != null");

            ODataResource resource = resourceState.Resource;

            // expectedResourceTypeName : if expected is of base type. but the resource real type is derived,
            // we need to set the resource type name.
            //      Writing response: expected type info can be identical with context uri info.
            //      Writing request: contextUri may not be provided, we always use the type from metadata info.
            //                       From model: if the resource can be found in model.
            //                       From serializationInfo: if user set the serializationInfo for the resource.
            string expectedResourceTypeName = null;

            if (this.WritingResponse)
            {
                expectedResourceTypeName = resourceState.GetOrCreateTypeContext(this.WritingResponse).ExpectedResourceTypeName;
            }
            else
            {
                if (resourceState.ResourceTypeFromMetadata == null)
                {
                    expectedResourceTypeName = resourceState.SerializationInfo == null
                     ? null
                     : resourceState.SerializationInfo.ExpectedTypeName;
                }
                else
                {
                    expectedResourceTypeName = resourceState.ResourceTypeFromMetadata.FullTypeName();
                }
            }

            // Write the "@odata.type": "typename"
            string typeName = this.JsonLightOutputContext.TypeNameOracle.GetResourceTypeNameForWriting(
                expectedResourceTypeName,
                resource,
                resourceState.IsUndeclared);

            if (typeName != null)
            {
                this.ODataAnnotationWriter.WriteODataTypeInstanceAnnotation(typeName);
            }

            // uncomment the below if decide to expose OData information via .InstanceAnnotations
            // else
            // {
            //    // close path for roundtrip :
            //    // write it to the wire if @odata.type is ever read from payload into Resource.InstanceAnnotations.
            //    ODataInstanceAnnotation odataTypeAnnotation = resource.InstanceAnnotations.FirstOrDefault(
            //        s => string.Equals(ODataAnnotationNames.ODataType, s.Name, StringComparison.OrdinalIgnoreCase));
            //    if (odataTypeAnnotation != null)
            //    {
            //        string rawTypeName = (string)odataTypeAnnotation.Value.FromODataValue();
            //        this.ODataAnnotationWriter.WriteODataTypeInstanceAnnotation(rawTypeName, writeRawValue: true);
            //    }
            // }
            // Write the "@odata.id": "Entity Id"
            Uri id;

            if (resource.MetadataBuilder.TryGetIdForSerialization(out id))
            {
                this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataId);
                if (id != null && !resource.HasNonComputedId)
                {
                    id = this.MetadataDocumentBaseUri.MakeRelativeUri(id);
                }

                this.JsonWriter.WriteValue(id == null ? null : this.UriToString(id));
            }

            // Write the "@odata.etag": "ETag value"
            string etag = resource.ETag;

            if (etag != null)
            {
                this.ODataAnnotationWriter.WriteInstanceAnnotationName(ODataAnnotationNames.ODataETag);
                this.JsonWriter.WriteValue(etag);
            }
        }