/// <summary>
        /// Gets the payload type name for an OData OM instance for JsonLight.
        /// </summary>
        /// <param name="payloadItem">The payload item to get the type name for.</param>
        /// <returns>The type name as read from the payload item (or constructed for primitive items).</returns>
        internal static string GetPayloadTypeName(object payloadItem)
        {
            if (payloadItem == null)
            {
                return(null);
            }

            TypeCode typeCode = ODataPlatformHelper.GetTypeCode(payloadItem.GetType());

            switch (typeCode)
            {
            // In JSON only boolean, String, Int32 and Double are recognized as primitive types
            // (without additional type conversion). So only check for those; if not one of these primitive
            // types it must be a complex, entity or collection value.
            case TypeCode.Boolean: return(Metadata.EdmConstants.EdmBooleanTypeName);

            case TypeCode.String: return(Metadata.EdmConstants.EdmStringTypeName);

            case TypeCode.Int32: return(Metadata.EdmConstants.EdmInt32TypeName);

            case TypeCode.Double: return(Metadata.EdmConstants.EdmDoubleTypeName);

            default:
                Debug.Assert(typeCode == TypeCode.Object, "If not one of the primitive types above, it must be an object in JSON.");
                break;
            }

            ODataComplexValue complexValue = payloadItem as ODataComplexValue;

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

            ODataCollectionValue collectionValue = payloadItem as ODataCollectionValue;

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

            ODataEntry entry = payloadItem as ODataEntry;

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

            throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightReader_ReadEntryStart));
        }
Beispiel #2
0
        internal static object CoerceNumericType(object primitiveValue, IEdmPrimitiveType targetEdmType)
        {
            // This is implemented to match TypePromotionUtils and MetadataUtilsCommon.CanConvertPrimitiveTypeTo()
            ExceptionUtils.CheckArgumentNotNull(primitiveValue, "primitiveValue");
            ExceptionUtils.CheckArgumentNotNull(targetEdmType, "targetEdmType");

            Type                 fromType            = primitiveValue.GetType();
            TypeCode             fromTypeCode        = ODataPlatformHelper.GetTypeCode(fromType);
            EdmPrimitiveTypeKind targetPrimitiveKind = targetEdmType.PrimitiveKind;

            switch (fromTypeCode)
            {
            case TypeCode.SByte:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.SByte:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int16:
                    return(Convert.ToInt16((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((SByte)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((SByte)primitiveValue));
                }

                break;

            case TypeCode.Byte:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Byte:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int16:
                    return(Convert.ToInt16((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Byte)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Byte)primitiveValue));
                }

                break;

            case TypeCode.Int16:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int16:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int32:
                    return(Convert.ToInt32((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int16)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int16)primitiveValue));
                }

                break;

            case TypeCode.Int32:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int32:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Int64:
                    return(Convert.ToInt64((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int32)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int32)primitiveValue));
                }

                break;

            case TypeCode.Int64:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Int64:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Single:
                    return(Convert.ToSingle((Int64)primitiveValue));

                case EdmPrimitiveTypeKind.Double:
                    return(Convert.ToDouble((Int64)primitiveValue));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Int64)primitiveValue));
                }

                break;

            case TypeCode.Single:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Single:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Double:
                    /*to string then to double, avoid losing precision like "(double)123.001f" which is 123.00099945068359, instead of 123.001d.*/
                    return(double.Parse(((Single)primitiveValue).ToString("R", CultureInfo.InvariantCulture), CultureInfo.InvariantCulture));

                case EdmPrimitiveTypeKind.Decimal:
                    return(Convert.ToDecimal((Single)primitiveValue));
                }

                break;

            case TypeCode.Double:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Double:
                    return(primitiveValue);

                case EdmPrimitiveTypeKind.Decimal:
                    // TODO: extract these convertion steps to an individual function
                    decimal doubleToDecimalR;

                    // To keep the full presion of the current value, which if necessary is all 17 digits of precision supported by the Double type.
                    if (decimal.TryParse(((Double)primitiveValue).ToString("R", CultureInfo.InvariantCulture), out doubleToDecimalR))
                    {
                        return(doubleToDecimalR);
                    }

                    return(Convert.ToDecimal((Double)primitiveValue));
                }

                break;

            case TypeCode.Decimal:
                switch (targetPrimitiveKind)
                {
                case EdmPrimitiveTypeKind.Decimal:
                    return(primitiveValue);
                }

                break;

            default:
                break;
            }

            return(null);
        }
        /// <summary>
        /// Writes a primitive value.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="value">The value to write.</param>
        internal static void WritePrimitiveValue(this IJsonWriter jsonWriter, object value)
        {
            TypeCode typeCode = ODataPlatformHelper.GetTypeCode(value.GetType());

            switch (typeCode)
            {
            case TypeCode.Boolean:
                jsonWriter.WriteValue((bool)value);
                break;

            case TypeCode.Byte:
                jsonWriter.WriteValue((byte)value);
                break;

            case TypeCode.Decimal:
                jsonWriter.WriteValue((decimal)value);
                break;

            case TypeCode.Double:
                jsonWriter.WriteValue((double)value);
                break;

            case TypeCode.Int16:
                jsonWriter.WriteValue((Int16)value);
                break;

            case TypeCode.Int32:
                jsonWriter.WriteValue((Int32)value);
                break;

            case TypeCode.Int64:
                jsonWriter.WriteValue((Int64)value);
                break;

            case TypeCode.SByte:
                jsonWriter.WriteValue((sbyte)value);
                break;

            case TypeCode.Single:
                jsonWriter.WriteValue((Single)value);
                break;

            case TypeCode.String:
                jsonWriter.WriteValue((string)value);
                break;

            default:
            {
                byte[] valueAsByteArray = value as byte[];
                if (valueAsByteArray != null)
                {
                    jsonWriter.WriteValue(valueAsByteArray);
                    break;
                }

                if (value is DateTimeOffset)
                {
                    jsonWriter.WriteValue((DateTimeOffset)value);
                    break;
                }

                if (value is Guid)
                {
                    jsonWriter.WriteValue((Guid)value);
                    break;
                }

                if (value is TimeSpan)
                {
                    jsonWriter.WriteValue((TimeSpan)value);
                    break;
                }
            }

                throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(value.GetType().FullName));
            }
        }