/// <summary> /// Converts a value to primitive value. /// </summary> /// <param name="value">The value.</param> /// <param name="propertyType">Type of the property.</param> /// <returns>The converted value if the value can be converted</returns> internal object ConvertPrimitiveValue(object value, Type propertyType) { // System.Xml.Linq.XElement and System.Data.Linq.Binaries primitive types are not supported by ODataLib directly, // so if the property is of one of those types, we need to convert the value to that type here. if (propertyType != null && value != null) { Debug.Assert(PrimitiveType.IsKnownNullableType(propertyType), "GetPrimitiveValue must be called only for primitive types"); // Fast path for the supported primitive types that have a type code and are supported by ODataLib. Type nonNullablePropertyType = Nullable.GetUnderlyingType(propertyType) ?? propertyType; TypeCode typeCode = PlatformHelper.GetTypeCode(nonNullablePropertyType); switch (typeCode) { case TypeCode.Boolean: // fall through case TypeCode.Byte: // fall through case TypeCode.DateTime: // fall through case TypeCode.Decimal: // fall through case TypeCode.Double: // fall through case TypeCode.Int16: // fall through case TypeCode.Int32: // fall through case TypeCode.Int64: // fall through case TypeCode.SByte: // fall through case TypeCode.Single: // fall through case TypeCode.String: return(this.ConvertValueIfNeeded(value, propertyType)); } // Do the conversion for types that are not supported by ODataLib e.g. char[], char, etc // PropertyType might be nullable. Hence to avoid nullable checks, we currently check for // primitiveType.ClrType if (typeCode == TypeCode.Char || typeCode == TypeCode.UInt16 || typeCode == TypeCode.UInt32 || typeCode == TypeCode.UInt64 || nonNullablePropertyType == typeof(Char[]) || nonNullablePropertyType == typeof(Type) || nonNullablePropertyType == typeof(Uri) || nonNullablePropertyType == typeof(Xml.Linq.XDocument) || nonNullablePropertyType == typeof(Xml.Linq.XElement)) { PrimitiveType primitiveType; PrimitiveType.TryGetPrimitiveType(propertyType, out primitiveType); Debug.Assert(primitiveType != null, "must be a known primitive type"); string stringValue = (string)this.ConvertValueIfNeeded(value, typeof(string)); return(primitiveType.TypeConverter.Parse(stringValue)); } #if !ASTORIA_LIGHT && !PORTABLELIB if (propertyType == BinaryTypeConverter.BinaryType) { byte[] byteArray = (byte[])this.ConvertValueIfNeeded(value, typeof(byte[])); Debug.Assert(byteArray != null, "If the property is of type System.Data.Linq.Binary then ODataLib should have read it as byte[]."); return(Activator.CreateInstance(BinaryTypeConverter.BinaryType, byteArray)); } #endif } return(this.ConvertValueIfNeeded(value, propertyType)); }
/// <summary> /// Converts a primitive OData value to the corresponding <see cref="IEdmDelayedValue"/>. /// </summary> /// <param name="primitiveValue">The primitive OData value to convert.</param> /// <param name="type">The <see cref="IEdmTypeReference"/> for the primitive value (if available).</param> /// <returns>An <see cref="IEdmDelayedValue"/> for the <paramref name="primitiveValue"/>.</returns> internal static IEdmDelayedValue ConvertPrimitiveValue(object primitiveValue, IEdmPrimitiveTypeReference type) { #if !ASTORIA_CLIENT DebugUtils.CheckNoExternalCallers(); #endif Debug.Assert(primitiveValue != null, "primitiveValue != null"); TypeCode typeCode = PlatformHelpers.GetTypeCode(primitiveValue.GetType()); switch (typeCode) { case TypeCode.Boolean: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Boolean); return(new EdmBooleanConstant(type, (bool)primitiveValue)); case TypeCode.Byte: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Byte); return(new EdmIntegerConstant(type, (byte)primitiveValue)); case TypeCode.SByte: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.SByte); return(new EdmIntegerConstant(type, (sbyte)primitiveValue)); case TypeCode.Int16: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Int16); return(new EdmIntegerConstant(type, (Int16)primitiveValue)); case TypeCode.Int32: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Int32); return(new EdmIntegerConstant(type, (Int32)primitiveValue)); case TypeCode.Int64: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Int64); return(new EdmIntegerConstant(type, (Int64)primitiveValue)); case TypeCode.DateTime: IEdmTemporalTypeReference dateTimeType = (IEdmTemporalTypeReference)EnsurePrimitiveType(type, EdmPrimitiveTypeKind.DateTime); return(new EdmDateTimeConstant(dateTimeType, (DateTime)primitiveValue)); case TypeCode.Decimal: IEdmDecimalTypeReference decimalType = (IEdmDecimalTypeReference)EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Decimal); return(new EdmDecimalConstant(decimalType, (decimal)primitiveValue)); case TypeCode.Single: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Single); return(new EdmFloatingConstant(type, (Single)primitiveValue)); case TypeCode.Double: type = EnsurePrimitiveType(type, EdmPrimitiveTypeKind.Double); return(new EdmFloatingConstant(type, (double)primitiveValue)); case TypeCode.String: IEdmStringTypeReference stringType = (IEdmStringTypeReference)EnsurePrimitiveType(type, EdmPrimitiveTypeKind.String); return(new EdmStringConstant(stringType, (string)primitiveValue)); default: return(ConvertPrimitiveValueWithoutTypeCode(primitiveValue, type)); } }
/// <summary> /// Converts a non-spatial primitive value to the target type. /// </summary> /// <param name="value">The value to convert.</param> /// <param name="targetType">The target type of the conversion.</param> /// <returns>The converted value.</returns> private static object ConvertNonSpatialValue(object value, Type targetType) { Debug.Assert(value != null, "value != null"); TypeCode targetTypeCode = PlatformHelper.GetTypeCode(targetType); // These types can be safely converted to directly, as there is no risk of precision being lost. switch (targetTypeCode) { case TypeCode.Boolean: case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: return(Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture)); } string stringValue = ClientConvert.ToString(value); return(ClientConvert.ChangeType(stringValue, targetType)); }