/// <summary> /// Returns the primitive property value. /// </summary> /// <param name="propertyValue">Value of the property.</param> /// <param name="propertyType">Type of the property.</param> /// <returns>Returns the value of the primitive property.</returns> internal static object ConvertPrimitiveValueToRecognizedODataType(object propertyValue, Type propertyType) { Debug.Assert(PrimitiveType.IsKnownNullableType(propertyType), "GetPrimitiveValue must be called only for primitive types"); Debug.Assert(propertyValue == null || PrimitiveType.IsKnownType(propertyValue.GetType()), "GetPrimitiveValue method must be called for primitive values only"); if (propertyValue == null) { return(null); } PrimitiveType primitiveType; PrimitiveType.TryGetPrimitiveType(propertyType, out primitiveType); Debug.Assert(primitiveType != null, "must be a known primitive type"); // Do the conversion for types that are not supported by ODataLib e.g. char[], char, etc if (propertyType == typeof(Char) || propertyType == typeof(Char[]) || propertyType == typeof(Type) || propertyType == typeof(Uri) || propertyType == typeof(System.Xml.Linq.XDocument) || propertyType == typeof(System.Xml.Linq.XElement)) { return(primitiveType.TypeConverter.ToString(propertyValue)); } else if (propertyType == typeof(DateTime)) { return(PlatformHelper.ConvertDateTimeToDateTimeOffset((DateTime)propertyValue)); } #if !PORTABLELIB else if (propertyType.FullName == "System.Data.Linq.Binary") { // For System.Data.Linq.Binary, it is a delay loaded type. Hence checking it based on name. // PrimitiveType.IsKnownType checks for binary type based on name and assembly. Hence just // checking name here is sufficient, since any other type with the same name, but in different // assembly will return false for PrimitiveType.IsKnownNullableType. // Since ODataLib does not understand binary type, we need to convert the value to byte[]. return(((BinaryTypeConverter)primitiveType.TypeConverter).ToArray(propertyValue)); } #endif else if (primitiveType.EdmTypeName == null) { // case StorageType.DateTimeOffset: // case StorageType.TimeSpan: // case StorageType.UInt16: // case StorageType.UInt32: // case StorageType.UInt64: // don't support reverse mappings for these types in this version // allows us to add real server support in the future without a // "breaking change" in the future client throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(propertyType.Name)); } return(propertyValue); }
/// <summary> /// Formats the literal without a type prefix, quotes, or escaping. /// </summary> /// <param name="value">The non-null value to format.</param> /// <returns>The formatted literal, without type marker or quotes.</returns> private static string FormatRawLiteral(object value) { Debug.Assert(value != null, "value != null"); string stringValue = value as string; if (stringValue != null) { return(stringValue); } if (value is bool) { return(XmlConvert.ToString((bool)value)); } if (value is byte) { return(XmlConvert.ToString((byte)value)); } #if ODATA_SERVICE || ODATA_CLIENT if (value is DateTime) { // Since the server/client supports DateTime values, convert the DateTime value // to DateTimeOffset and use XmlConvert to convert to String. // If datetime kind is unspecified, then treat it as UTC. #if ODATA_SERVICE DateTimeOffset dto = WebUtil.ConvertDateTimeToDateTimeOffset((DateTime)value); #elif ODATA_CLIENT DateTimeOffset dto = PlatformHelper.ConvertDateTimeToDateTimeOffset((DateTime)value); #endif return(XmlConvert.ToString(dto)); } #endif if (value is decimal) { return(XmlConvert.ToString((decimal)value)); } if (value is double) { string formattedDouble = XmlConvert.ToString((double)value); formattedDouble = SharedUtils.AppendDecimalMarkerToDouble(formattedDouble); return(formattedDouble); } if (value is Guid) { return(value.ToString()); } if (value is short) { return(XmlConvert.ToString((Int16)value)); } if (value is int) { return(XmlConvert.ToString((Int32)value)); } if (value is long) { return(XmlConvert.ToString((Int64)value)); } if (value is sbyte) { return(XmlConvert.ToString((SByte)value)); } if (value is float) { return(XmlConvert.ToString((Single)value)); } byte[] array = value as byte[]; if (array != null) { return(ConvertByteArrayToKeyString(array)); } if (value is Date) { return(value.ToString()); } if (value is DateTimeOffset) { return(XmlConvert.ToString((DateTimeOffset)value)); } if (value is TimeOfDay) { return(value.ToString()); } if (value is TimeSpan) { return(EdmValueWriter.DurationAsXml((TimeSpan)value)); } Geography geography = value as Geography; if (geography != null) { return(WellKnownTextSqlFormatter.Create(true).Write(geography)); } Geometry geometry = value as Geometry; if (geometry != null) { return(WellKnownTextSqlFormatter.Create(true).Write(geometry)); } ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.Value); } throw SharedUtils.CreateExceptionForUnconvertableType(value); }
/// <summary> /// Converts the object to ODataValue, the result could be null, the original primitive object, ODataNullValue, /// ODataEnumValue, ODataCollectionValue, ODataResource, ODataEntityReferenceLinks, ODataEntityReferenceLinks, or /// a list of ODataResource. /// </summary> /// <param name="paramName">The name of the <see cref="UriOperationParameter"/>. Used for error reporting.</param> /// <param name="value">The value of the <see cref="UriOperationParameter"/>.</param> /// <param name="needsSpecialEscaping">True if the result need special escaping.</param> /// <param name="useEntityReference">If true, use entity reference, instead of entity to serialize the parameter.</param> /// <returns>The converted result.</returns> private object ConvertToODataValue(string paramName, object value, ref bool needsSpecialEscaping, bool useEntityReference) { Object valueInODataFormat = null; if (value == null) { needsSpecialEscaping = true; } else if (value is ODataNullValue) { valueInODataFormat = value; needsSpecialEscaping = true; } else { ClientEdmModel model = this.requestInfo.Model; IEdmType edmType = model.GetOrCreateEdmType(value.GetType()); Debug.Assert(edmType != null, "edmType != null"); ClientTypeAnnotation typeAnnotation = model.GetClientTypeAnnotation(edmType); Debug.Assert(typeAnnotation != null, "typeAnnotation != null"); switch (edmType.TypeKind) { case EdmTypeKind.Primitive: // Client lib internal conversion to support DateTime if (value is DateTime) { valueInODataFormat = PlatformHelper.ConvertDateTimeToDateTimeOffset((DateTime)value); } else { valueInODataFormat = value; } needsSpecialEscaping = true; break; case EdmTypeKind.Enum: string typeNameInEdm = this.requestInfo.GetServerTypeName(model.GetClientTypeAnnotation(edmType)); valueInODataFormat = new ODataEnumValue( ClientTypeUtil.GetEnumValuesString(value.ToString(), typeAnnotation.ElementType), typeNameInEdm ?? typeAnnotation.ElementTypeName); needsSpecialEscaping = true; break; case EdmTypeKind.Collection: IEdmCollectionType edmCollectionType = edmType as IEdmCollectionType; Debug.Assert(edmCollectionType != null, "edmCollectionType != null"); IEdmTypeReference itemTypeReference = edmCollectionType.ElementType; Debug.Assert(itemTypeReference != null, "itemTypeReference != null"); ClientTypeAnnotation itemTypeAnnotation = model.GetClientTypeAnnotation(itemTypeReference.Definition); Debug.Assert(itemTypeAnnotation != null, "itemTypeAnnotation != null"); valueInODataFormat = ConvertToCollectionValue(paramName, value, itemTypeAnnotation, useEntityReference); break; case EdmTypeKind.Complex: case EdmTypeKind.Entity: Debug.Assert(edmType.TypeKind == EdmTypeKind.Complex || value != null, "edmType.TypeKind == EdmTypeKind.Complex || value != null"); Debug.Assert(typeAnnotation != null, "typeAnnotation != null"); valueInODataFormat = ConvertToEntityValue(value, typeAnnotation.ElementType, useEntityReference); break; default: // EdmTypeKind.Row // EdmTypeKind.EntityReference throw new NotSupportedException(Strings.Serializer_InvalidParameterType(paramName, edmType.TypeKind)); } Debug.Assert(valueInODataFormat != null, "valueInODataFormat != null"); } return(valueInODataFormat); }