예제 #1
0
        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));
        }
예제 #2
0
        /// <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.");
        }
예제 #4
0
        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);
        }
예제 #7
0
        /// <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());
        }
예제 #8
0
        /// <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;
        }
예제 #11
0
        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"]);
        }
예제 #14
0
 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);
 }
예제 #16
0
        /// <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"]);
        }
예제 #19
0
        /// <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()
     );
 }
예제 #21
0
 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\"]}"
            );
        }
예제 #23
0
        /// <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()
     );
 }
예제 #25
0
 public void IfValueIsEnumThenODataValueShouldBeReferenceEqual()
 {
     var enumValue = new ODataEnumValue(Color.Green.ToString());
     this.property.Value = enumValue;
     this.property.ODataValue.Should().BeSameAs(enumValue);
 }
예제 #26
0
        /// <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();
 }
예제 #28
0
        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
                });
            }
        }
예제 #29
0
        /// <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;
        }