public void ConvertEnumValue_ReturnEnumValue_ForEnumType() { // Arrange object value = new ODataEnumValue("Red"); Type type = typeof(Color); // Act & Assert Assert.Equal(Enum.ToObject(typeof(Color), Color.Red), EnumDeserializationHelpers.ConvertEnumValue(value, type)); }
/// <summary> /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified, /// derive the type from the model type (if available). /// </summary> /// <param name="model">The model to use.</param> /// <param name="enumValue">The value in question to resolve the type for.</param> /// <param name="isOpenPropertyType">True if the type name belongs to an open property.</param> /// <returns>A type for the <paramref name="enumValue"/> or null if no type name is specified and no metadata is available.</returns> internal static IEdmTypeReference ResolveAndValidateTypeForEnumValue(IEdmModel model, ODataEnumValue enumValue, bool isOpenPropertyType) { Debug.Assert(model != null, "model != null"); ValidateIfTypeNameMissing(enumValue.TypeName, model, isOpenPropertyType); // starting from enum type, we want to skip validation (but still let the above makes sure open type's enum value has .TypeName) return null; }
public void ConvertEnumValue_Throws_ForNonEnumType() { // Arrange object value = new ODataEnumValue("Red"); Type type = typeof(int); // Act & Assert Assert.Throws<InvalidOperationException>( () => EnumDeserializationHelpers.ConvertEnumValue(value, type), "The type 'Int32' must be an enum or Nullable<T> where T is an enum type."); }
public void ConvertEnumValue_Throws_ForNullTypeParameter() { // Arrange object value = new ODataEnumValue("Red"); Type type = null; // Act & Assert Assert.ThrowsArgumentNull( () => EnumDeserializationHelpers.ConvertEnumValue(value, type), "type"); }
public void AddTypeNameAnnotationAsNeeded_DoesNotAddAnnotation() { // Arrange ODataEnumValue enumValue = new ODataEnumValue("value"); IEdmEnumTypeReference enumType = new EdmEnumTypeReference( new EdmEnumType("TestModel", "EnumType"), isNullable: false); // Act ODataEnumSerializer.AddTypeNameAnnotationAsNeeded(enumValue, enumType, ODataMetadataLevel.MinimalMetadata); // Assert SerializationTypeNameAnnotation annotation = enumValue.GetAnnotation<SerializationTypeNameAnnotation>(); Assert.Null(annotation); }
public override string ConvertValueToUriLiteral(object value, bool escapeDataString) { if (value != null && value.GetType().IsEnumType()) value = new ODataEnumValue(value.ToString(), _session.Metadata.GetQualifiedTypeName(value.GetType().Name)); var odataVersion = (ODataVersion)Enum.Parse(typeof(ODataVersion), _session.Adapter.GetODataVersionString(), false); Func<object, string> convertValue = x => ODataUriUtils.ConvertToUriLiteral(x, odataVersion, (_session.Adapter as ODataAdapter).Model); return value is ODataExpression ? (value as ODataExpression).AsString(_session) : escapeDataString ? Uri.EscapeDataString(convertValue(value)) : convertValue(value); }
/// <summary> /// Gets the type name from the given <paramref name="value"/>. /// </summary> /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param> /// <returns>The type name for the given <paramref name="value"/>.</returns> protected static string GetTypeNameFromValue(object value) { Debug.Assert(value != null, "value != null"); ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue; if (primitiveValue != null) { // primitiveValueTypeReference == null means: the EDM type of the primitive value cannot be determined. // This could possibly be due to value being an unsigned int. // In this case, simply return null because: // - If the property is regular property, the type is not needed since service model knows its exact type. // - If the property is dynamic property, ODL does not support dynamic property containing unsigned int value // since we don't know its underlying type as well as how to serialize it. IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()); return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.ODataFullName()); } ODataComplexValue complexValue = value as ODataComplexValue; if (complexValue != null) { return(complexValue.TypeName); } ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } return(primitiveTypeReference.ODataFullName()); }
/// <summary> /// Gets the type name from the given <paramref name="value"/>. /// </summary> /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataComplexValue, an ODataCollectionValue or a Clr primitive object.</param> /// <returns>The type name for the given <paramref name="value"/>.</returns> protected static string GetTypeNameFromValue(object value) { Debug.Assert(value != null, "value != null"); ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue; if (primitiveValue != null) { return(EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType()).ODataFullName()); } ODataComplexValue complexValue = value as ODataComplexValue; if (complexValue != null) { return(complexValue.TypeName); } ODataEnumValue enumValue = value as ODataEnumValue; if (enumValue != null) { return(enumValue.TypeName); } ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName)); } IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (primitiveTypeReference == null) { throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } return(primitiveTypeReference.ODataFullName()); }
/// <summary> /// Creates an <see cref="ODataEnumValue"/> for the object represented by <paramref name="graph"/>. /// </summary> /// <param name="graph">The enum value.</param> /// <param name="enumType">The EDM enum type of the value.</param> /// <param name="writeContext">The serializer write context.</param> /// <returns>The created <see cref="ODataEnumValue"/>.</returns> public virtual ODataEnumValue CreateODataEnumValue(object graph, IEdmEnumTypeReference enumType, ODataSerializerContext writeContext) { if (graph == null) { return null; } string value = null; if (graph.GetType().IsEnum) { value = graph.ToString(); } ODataEnumValue enumValue = new ODataEnumValue(value, enumType.FullName()); ODataMetadataLevel metadataLevel = writeContext != null ? writeContext.MetadataLevel : ODataMetadataLevel.Default; AddTypeNameAnnotationAsNeeded(enumValue, enumType, metadataLevel); return enumValue; }
/// <summary>Materializes an enum value. No op or non-primitive values.</summary> /// <param name="enumType">The clr Type of value to set.</param> /// <param name="enumValue">The value of enum.</param> /// <returns>The materialized value.</returns> internal static object MaterializeODataEnumValue(Type enumType, ODataEnumValue enumValue) { object tmpValue; if (enumValue == null) { tmpValue = null; } else { // TODO: Find better way to parse Enum string enumValueStr = enumValue.Value.Trim(); if (!Enum.IsDefined(enumType, enumValueStr)) { tmpValue = Enum.Parse(enumType, ClientTypeUtil.GetClientFieldName(enumType, enumValueStr), false); } else { tmpValue = Enum.Parse(enumType, enumValueStr, false); } } return tmpValue; }
private static object ConvertEnumValue(ODataEnumValue enumValue, ref IEdmTypeReference propertyType, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext) { IEdmEnumTypeReference edmEnumType; if (propertyType == null) { // dynamic enum property Contract.Assert(!String.IsNullOrEmpty(enumValue.TypeName), "ODataLib should have verified that dynamic enum value has a type name since we provided metadata."); IEdmModel model = readContext.Model; IEdmType edmType = model.FindType(enumValue.TypeName); Contract.Assert(edmType.TypeKind == EdmTypeKind.Enum, "ODataLib should have verified that enum value has a enum resource type."); edmEnumType = new EdmEnumTypeReference(edmType as IEdmEnumType, isNullable: true); propertyType = edmEnumType; } else { edmEnumType = propertyType.AsEnum(); } ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(edmEnumType); return deserializer.ReadInline(enumValue, propertyType, readContext); }
public void ReadComplexValue_CanReadDynamicCollectionPropertiesForOpenComplexType() { // Arrange ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.ComplexType<SimpleOpenAddress>(); builder.EnumType<SimpleEnum>(); IEdmModel model = builder.GetEdmModel(); IEdmComplexTypeReference addressTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenAddress)).AsComplex(); var deserializerProvider = new DefaultODataDeserializerProvider(); var deserializer = new ODataComplexTypeDeserializer(deserializerProvider); ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName); ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "Collection(" + typeof(SimpleEnum).FullName + ")", Items = new[] { enumValue, enumValue } }; ODataComplexValue complexValue = new ODataComplexValue { Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "My Way #599" }, // dynamic properties new ODataProperty { Name = "CollectionProperty", Value = collectionValue } }, TypeName = typeof(SimpleOpenAddress).FullName }; ODataDeserializerContext readContext = new ODataDeserializerContext() { Model = model }; // Act SimpleOpenAddress address = deserializer.ReadComplexValue(complexValue, addressTypeReference, readContext) as SimpleOpenAddress; // Assert Assert.NotNull(address); // Verify the declared properties Assert.Equal("My Way #599", address.Street); Assert.Null(address.City); // Verify the dynamic properties Assert.NotNull(address.Properties); Assert.Equal(1, address.Properties.Count()); var collectionValues = Assert.IsType<List<SimpleEnum>>(address.Properties["CollectionProperty"]); Assert.NotNull(collectionValues); Assert.Equal(2, collectionValues.Count()); Assert.Equal(SimpleEnum.Third, collectionValues[0]); Assert.Equal(SimpleEnum.Third, collectionValues[1]); }
public void ReadComplexValue_CanReadDynamicPropertiesForOpenComplexType() { // Arrange ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.ComplexType<SimpleOpenAddress>(); builder.EnumType<SimpleEnum>(); IEdmModel model = builder.GetEdmModel(); IEdmComplexTypeReference addressTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenAddress)).AsComplex(); var deserializerProvider = new Mock<ODataDeserializerProvider>().Object; var deserializer = new ODataComplexTypeDeserializer(deserializerProvider); ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName); ODataComplexValue complexValue = new ODataComplexValue { Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "My Way #599" }, new ODataProperty { Name = "City", Value = "Redmond & Shanghai" }, // dynamic properties new ODataProperty { Name = "GuidProperty", Value = new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA") }, new ODataProperty { Name = "EnumValue", Value = enumValue }, new ODataProperty { Name = "DateTimeProperty", Value = new DateTimeOffset(new DateTime(1992, 1, 1)) } }, TypeName = typeof(SimpleOpenAddress).FullName }; ODataDeserializerContext readContext = new ODataDeserializerContext() { Model = model }; // Act SimpleOpenAddress address = deserializer.ReadComplexValue(complexValue, addressTypeReference, readContext) as SimpleOpenAddress; // Assert Assert.NotNull(address); // Verify the declared properties Assert.Equal("My Way #599", address.Street); Assert.Equal("Redmond & Shanghai", address.City); // Verify the dynamic properties Assert.NotNull(address.Properties); Assert.Equal(3, address.Properties.Count()); Assert.Equal(new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA"), address.Properties["GuidProperty"]); Assert.Equal(SimpleEnum.Third, address.Properties["EnumValue"]); Assert.Equal(new DateTimeOffset(new DateTime(1992, 1, 1)), address.Properties["DateTimeProperty"]); }
public void TestEnumConvertToUriLiteral_EnumValue() { var val = new ODataEnumValue(11L + "", "Fully.Qualified.Namespace.ColorPattern"); string enumValStr = ODataUriUtils.ConvertToUriLiteral(val, ODataVersion.V4); enumValStr.Should().Be("Fully.Qualified.Namespace.ColorPattern'11'"); }
private static void AssertODataEnumValueAreEqual(ODataEnumValue expectedEnumValue, ODataEnumValue actualEnumValue) { Assert.IsNotNull(expectedEnumValue); Assert.IsNotNull(actualEnumValue); Assert.AreEqual(expectedEnumValue.Value, actualEnumValue.Value); Assert.AreEqual(expectedEnumValue.TypeName, actualEnumValue.TypeName); }
/// <summary> /// Creates an <see cref="ODataEnumValue"/> for the object represented by <paramref name="graph"/>. /// </summary> /// <param name="graph">The enum value.</param> /// <param name="enumType">The EDM enum type of the value.</param> /// <param name="writeContext">The serializer write context.</param> /// <returns>The created <see cref="ODataEnumValue"/>.</returns> public virtual Task<ODataEnumValue> CreateODataEnumValueAsync(object graph, IEdmEnumTypeReference enumType, ODataSerializerContext writeContext) { if (graph == null) { return null; } string value = null; if (graph.GetType().GetTypeInfo().IsEnum) { value = graph.ToString(); } else { if (graph.GetType() == typeof(EdmEnumObject)) { value = ((EdmEnumObject)graph).Value; } } ODataEnumValue enumValue = new ODataEnumValue(value, enumType.FullName()); ODataMetadataLevel metadataLevel = writeContext != null ? writeContext.MetadataLevel : ODataMetadataLevel.MinimalMetadata; AddTypeNameAnnotationAsNeeded(enumValue, enumType, metadataLevel); return Task.FromResult(enumValue); }
public void EnumTypeCollectionRoundtripJsonLightTest() { ODataEnumValue subject0 = new ODataEnumValue("Red", "NS.ColorFlags"); ODataEnumValue subject1 = new ODataEnumValue("123", "NS.ColorFlags"); ODataCollectionValue complexCollectionValue = new ODataCollectionValue { TypeName = "Collection(NS.ColorFlags)", Items = new[] { subject0, subject1 } }; this.VerifyNonPrimitiveTypeRoundtrip(complexCollectionValue, "ClothesColors"); }
public void ReadEntry_CanReadDynamicPropertiesForOpenEntityType() { // Arrange ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntityType<SimpleOpenCustomer>(); builder.EnumType<SimpleEnum>(); IEdmModel model = builder.GetEdmModel(); IEdmEntityTypeReference customerTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenCustomer)).AsEntity(); var deserializerProvider = new DefaultODataDeserializerProvider(); var deserializer = new ODataEntityDeserializer(deserializerProvider); ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName); ODataComplexValue[] complexValues = { new ODataComplexValue { TypeName = typeof(SimpleOpenAddress).FullName, Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "Street 1" }, new ODataProperty { Name = "City", Value = "City 1" }, // dynamic properties new ODataProperty { Name = "DateTimeProperty", Value = new DateTimeOffset(new DateTime(2014, 5, 6)) } } }, new ODataComplexValue { TypeName = typeof(SimpleOpenAddress).FullName, Properties = new[] { // declared properties new ODataProperty { Name = "Street", Value = "Street 2" }, new ODataProperty { Name = "City", Value = "City 2" }, // dynamic properties new ODataProperty { Name = "ArrayProperty", Value = new ODataCollectionValue { TypeName = "Collection(Edm.Int32)", Items = new[] {1, 2, 3, 4} } } } } }; ODataCollectionValue collectionValue = new ODataCollectionValue { TypeName = "Collection(" + typeof(SimpleOpenAddress).FullName + ")", Items = complexValues }; ODataEntry odataEntry = new ODataEntry { Properties = new[] { // declared properties new ODataProperty { Name = "CustomerId", Value = 991 }, new ODataProperty { Name = "Name", Value = "Name #991" }, // dynamic properties new ODataProperty { Name = "GuidProperty", Value = new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA") }, new ODataProperty { Name = "EnumValue", Value = enumValue }, new ODataProperty { Name = "CollectionProperty", Value = collectionValue } }, TypeName = typeof(SimpleOpenCustomer).FullName }; ODataDeserializerContext readContext = new ODataDeserializerContext() { Model = model }; ODataEntryWithNavigationLinks entry = new ODataEntryWithNavigationLinks(odataEntry); // Act SimpleOpenCustomer customer = deserializer.ReadEntry(entry, customerTypeReference, readContext) as SimpleOpenCustomer; // Assert Assert.NotNull(customer); // Verify the declared properties Assert.Equal(991, customer.CustomerId); Assert.Equal("Name #991", customer.Name); // Verify the dynamic properties Assert.NotNull(customer.CustomerProperties); Assert.Equal(3, customer.CustomerProperties.Count()); Assert.Equal(new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA"), customer.CustomerProperties["GuidProperty"]); Assert.Equal(SimpleEnum.Third, customer.CustomerProperties["EnumValue"]); // Verify the dynamic collection property var collectionValues = Assert.IsType<List<SimpleOpenAddress>>(customer.CustomerProperties["CollectionProperty"]); Assert.NotNull(collectionValues); Assert.Equal(2, collectionValues.Count()); Assert.Equal(new DateTimeOffset(new DateTime(2014, 5, 6)), collectionValues[0].Properties["DateTimeProperty"]); Assert.Equal(new List<int> { 1, 2, 3, 4 }, collectionValues[1].Properties["ArrayProperty"]); }
/// <summary> /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified, /// derive the type from the model type (if available). /// </summary> /// <param name="model">The model to use.</param> /// <param name="enumValue">The value in question to resolve the type for.</param> /// <param name="isOpenPropertyType">True if the type name belongs to an open property.</param> /// <returns>A type for the <paramref name="enumValue"/> or null if no type name is specified and no metadata is available.</returns> internal static IEdmTypeReference ResolveAndValidateTypeForEnumValue(IEdmModel model, ODataEnumValue enumValue, bool isOpenPropertyType) { Debug.Assert(model != null, "model != null"); ValidateIfTypeNameMissing(enumValue.TypeName, model, isOpenPropertyType); // starting from enum type, we want to skip validation (but still let the above makes sure open type's enum value has .TypeName) return(null); }
public void FlagsEnumAsTopLevelValue_StrAsValue_StrAsTypeName_anyContentType() { WriteToMessageWriterAndVerifyPayload( contentType: "*/*", writerAction: (writer) => { ODataEnumValue enumValue = new ODataEnumValue(Color.Red.ToString(), "NS.EnumUndefinedTypename"); writer.WriteValue(enumValue); }, expectedPayload: Color.Red.ToString() ); }
private static void AssertODataEnumValueAreEqual(ODataEnumValue enumValue1, ODataEnumValue enumValue2) { Assert.IsNotNull(enumValue1); Assert.IsNotNull(enumValue2); Assert.AreEqual(enumValue1.Value, enumValue2.Value); Assert.AreEqual(enumValue1.TypeName, enumValue2.TypeName); }
public void FlagsEnumAsCollectionItemAsTopLevelValue_StrAsValue_StrAsTypeName_MinimalMetadata_CollecionWriter() { ODataCollectionStart collectionStart = new ODataCollectionStart(); collectionStart.SetSerializationInfo(new ODataCollectionStartSerializationInfo { CollectionTypeName = "Collection(NS.ColorFlags)" }); ODataEnumValue[] items = new ODataEnumValue[] { new ODataEnumValue(ColorFlags.Red.ToString(), "NS.ColorFlags"), new ODataEnumValue(null, "NS.ColorFlags_Undefined"), new ODataEnumValue("Red,Green", "NS.ColorFlags"), new ODataEnumValue("Red|Green", "NS.ColorFlags"), new ODataEnumValue(ColorFlags.Green.ToString(), "NS.ColorFlags") }; EdmEnumTypeReference enumRef = new EdmEnumTypeReference((IEdmEnumType)this.userModel.FindType("NS.ColorFlags"), true); WriteToMessageWriterAndVerifyPayload( contentType: "application/json;odata.metadata=minimal;", writerAction: (writer) => { ODataCollectionWriter collectionWriter = writer.CreateODataCollectionWriter(enumRef); collectionWriter.WriteStart(collectionStart); foreach (object item in items) { collectionWriter.WriteItem(item); } collectionWriter.WriteEnd(); }, expectedPayload: "{\"@odata.context\":\"http://odata.org/test/$metadata#Collection(NS.ColorFlags)\",\"value\":[\"Red\",null,\"Red,Green\",\"Red|Green\",\"Green\"]}" ); }
/// <summary> /// ConstantExpression visit method /// </summary> /// <param name="c">The ConstantExpression expression to visit</param> /// <returns>The visited ConstantExpression expression </returns> internal override Expression VisitConstant(ConstantExpression c) { if (c.Value == null) { this.builder.Append(UriHelper.NULL); return c; } // DEVNOTE: // Rather than forcing every other codepath to have the 'Try...' pattern for formatting, // we catch the InvalidOperationException here to change the exception type. // This is exceedingly rare, and not a scenario where performance is meaningful, so the // reduced complexity in all other call sites is worth the extra logic here. string result; BinaryExpression b = this.parent as BinaryExpression; MethodCallExpression m = this.parent as MethodCallExpression; if ((b != null && HasEnumInBinaryExpression(b)) || (m != null && m.Method.Name == "HasFlag")) { c = this.ConvertConstantExpressionForEnum(c); ClientEdmModel model = this.context.Model; IEdmType edmType = model.GetOrCreateEdmType(c.Type.IsEnum() ? c.Type : c.Type.GetGenericArguments()[0]); ClientTypeAnnotation typeAnnotation = model.GetClientTypeAnnotation(edmType); string typeNameInEdm = this.context.ResolveNameFromTypeInternal(typeAnnotation.ElementType); MemberInfo member = typeAnnotation.ElementType.GetField(c.Value.ToString()); string memberValue = ClientTypeUtil.GetServerDefinedName(member); ODataEnumValue enumValue = new ODataEnumValue(memberValue, typeNameInEdm ?? typeAnnotation.ElementTypeName); result = ODataUriUtils.ConvertToUriLiteral(enumValue, CommonUtil.ConvertToODataVersion(this.uriVersion), null); } else { try { result = LiteralFormatter.ForConstants.Format(c.Value); } catch (InvalidOperationException) { if (this.cantTranslateExpression) { // there's already a problem in the parents. // we should just return here, because caller somewhere up the stack will throw a better exception return c; } throw new NotSupportedException(Strings.ALinq_CouldNotConvert(c.Value)); } } Debug.Assert(result != null, "result != null"); this.builder.Append(result); return c; }
public void FlagsEnumAsTopLevelValue_StrAsValue_StrAsTypeName_textplainContentType() { WriteToMessageWriterAndVerifyPayload( contentType: "text/plain", // can't be full/minimal/none metadata writerAction: (writer) => { ODataEnumValue enumValue = new ODataEnumValue(Color.Red.ToString(), "NS.EnumUndefinedTypename"); writer.WriteValue(enumValue); }, expectedPayload: Color.Red.ToString() ); }
public void IfValueIsEnumThenODataValueShouldBeReferenceEqual() { var enumValue = new ODataEnumValue(Color.Green.ToString()); this.property.Value = enumValue; this.property.ODataValue.Should().BeSameAs(enumValue); }
/// <summary> /// Converts the object to ODataValue, the result could be null, the original primitive object, ODataNullValue, /// ODataEnumValue, ODataCollectionValue, ODataEntry, ODataEntityReferenceLinks, ODataEntityReferenceLinks, or /// a list of ODataEntry. /// </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: 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.Complex: Debug.Assert(typeAnnotation != null, "typeAnnotation != null"); valueInODataFormat = this.propertyConverter.CreateODataComplexValue(typeAnnotation.ElementType, value, null, false, null); // When using JsonVerbose to format query string parameters for Actions, // we cannot write out Complex values in the URI without the type name of the complex type in the JSON payload. // If this value is null, the client has to set the ResolveName property on the DataServiceContext instance. ODataComplexValue complexValue = (ODataComplexValue)valueInODataFormat; SerializationTypeNameAnnotation serializedTypeNameAnnotation = complexValue.GetAnnotation<SerializationTypeNameAnnotation>(); if (serializedTypeNameAnnotation == null || string.IsNullOrEmpty(serializedTypeNameAnnotation.TypeName)) { throw Error.InvalidOperation(Strings.DataServiceException_GeneralError); } 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.Entity: 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; }
/// <summary> /// Write enum value /// </summary> /// <param name="value">enum value</param> /// <param name="expectedTypeReference">expected type reference</param> public void WriteEnumValue(ODataEnumValue value, IEdmTypeReference expectedTypeReference) { throw new NotImplementedException(); }
internal static void AddTypeNameAnnotationAsNeeded(ODataEnumValue enumValue, IEdmEnumTypeReference enumType, ODataMetadataLevel metadataLevel) { // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties // null when values should not be serialized. The TypeName property is different and should always be // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not // to serialize the type name (a null value prevents serialization). Contract.Assert(enumValue != null); // Only add an annotation if we want to override ODataLib's default type name serialization behavior. if (ShouldAddTypeNameAnnotation(metadataLevel)) { string typeName; // Provide the type name to serialize (or null to force it not to serialize). if (ShouldSuppressTypeNameSerialization(metadataLevel)) { typeName = null; } else { typeName = enumType.FullName(); } enumValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = typeName }); } }
/// <summary> /// Tries to convert the given value into an instance of <see cref="ODataValue"/>. /// </summary> /// <param name="property">The property being converted.</param> /// <param name="propertyValue">The property value to convert..</param> /// <param name="serverTypeName">The server type name of the entity whose properties are being populated.</param> /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param> /// <param name="odataValue">The odata value if one was created.</param> /// <returns>Whether or not the value was converted.</returns> private bool TryConvertPropertyValue(ClientPropertyAnnotation property, object propertyValue, string serverTypeName, HashSet<object> visitedComplexTypeObjects, out ODataValue odataValue) { if (property.IsKnownType) { odataValue = CreateODataPrimitivePropertyValue(property, propertyValue); return true; } if (property.IsEnumType) { string enumValue; if (propertyValue == null) { enumValue = null; } else { enumValue = ClientTypeUtil.GetEnumValuesString(propertyValue.ToString(), property.PropertyType); } string typeNameInMetadata = this.requestInfo.ResolveNameFromType(property.PropertyType); odataValue = new ODataEnumValue(enumValue, typeNameInMetadata); return true; } if (property.IsPrimitiveOrEnumOrComplexCollection) { odataValue = this.CreateODataCollectionPropertyValue(property, propertyValue, serverTypeName, visitedComplexTypeObjects); return true; } if (!property.IsEntityCollection && !ClientTypeUtil.TypeIsEntity(property.PropertyType, this.requestInfo.Model)) { odataValue = this.CreateODataComplexPropertyValue(property, propertyValue, visitedComplexTypeObjects); return true; } odataValue = null; return false; }