Exemple #1
0
        /// <summary>
        /// User hook to resolve name into a type.
        /// </summary>
        /// <param name="wireName">Name to resolve.</param>
        /// <param name="expectedType">Expected type for the name.</param>
        /// <returns>the type as returned by the resolver. If no resolver is registered or resolver returns null, expected type is returned.</returns>
        /// <exception cref="InvalidOperationException">if ResolveType function returns a type not assignable to the userType</exception>
        private Type ResolveTypeFromName(string wireName, Type expectedType)
        {
            Debug.Assert(!String.IsNullOrEmpty(wireName), "!String.IsNullOrEmpty(wireName)");
            Debug.Assert(expectedType != null, "userType != null");

            // If there is a mismatch between the wireName and expected type (For e.g. wireName is Edm.Int32 and expectedType is a complex type)
            // we will return Edm.Int32 from this method and ODatalib fails stating the type kind do not match.
            Type payloadType;

            if (!ClientConvert.ToNamedType(wireName, out payloadType))
            {
                payloadType = this.resolveTypeFromName(wireName);

                if (payloadType == null)
                {
                    // if the type resolution method returns null or the ResolveType property was not set
#if !PORTABLELIB
                    payloadType = ClientTypeCache.ResolveFromName(wireName, expectedType);
#else
                    payloadType = ClientTypeCache.ResolveFromName(wireName, expectedType, this.GetType());
#endif
                }

                if (!this.skipTypeAssignabilityCheck && (payloadType != null) && (!expectedType.IsAssignableFrom(payloadType)))
                {
                    // throw an exception if the type from the resolver is not assignable to the expected type
                    throw Error.InvalidOperation(Strings.Deserialize_Current(expectedType, payloadType));
                }
            }

            return(payloadType ?? expectedType);
        }
        public void ToNamedTypeTests()
        {
            Type t;

            Assert.IsTrue(ClientConvert.ToNamedType(String.Empty, out t));
            Assert.AreEqual(typeof(String), t);

            Assert.IsTrue(ClientConvert.ToNamedType(null, out t));
            Assert.AreEqual(typeof(String), t);

            Assert.IsTrue(ClientConvert.ToNamedType("Edm.TestPrimitive", out t));
            Assert.AreEqual(typeof(TestPrimitiveType), t);
        }
        /// <summary>
        /// Adds a data value to the dynamic properties dictionary (where it exists) on the specified <paramref name="instance"/>
        /// </summary>
        /// <param name="property">Property containing unmaterialzed value to apply</param>
        /// <param name="instance">Instance that may optionally contain the dynamic properties dictionary</param>
        internal void MaterializeDynamicProperty(ODataProperty property, object instance)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(instance != null, "instance != null");

            IDictionary <string, object> containerProperty;

            // Stop if owning type is not an open type
            // Or container property is not found
            // Or key with matching name already exists in the dictionary
            if (!ClientTypeUtil.IsInstanceOfOpenType(instance, this.MaterializerContext.Model) ||
                !ClientTypeUtil.TryGetContainerProperty(instance, out containerProperty) ||
                containerProperty.ContainsKey(property.Name))
            {
                return;
            }

            object value = property.Value;

            // Handles properties of known types returned with type annotations
            if (!(value is ODataValue) && PrimitiveType.IsKnownType(value.GetType()))
            {
                containerProperty.Add(property.Name, value);
                return;
            }

            // Handle untyped value
            ODataUntypedValue untypedVal = value as ODataUntypedValue;

            if (untypedVal != null)
            {
                value = CommonUtil.ParseJsonToPrimitiveValue(untypedVal.RawValue);
                containerProperty.Add(property.Name, value);
                return;
            }

            // Handle enum value
            ODataEnumValue enumVal = value as ODataEnumValue;

            if (enumVal != null)
            {
                Type clientType = ResolveClientTypeForDynamicProperty(enumVal.TypeName, instance);
                // Unable to resolve type for dynamic property
                if (clientType == null)
                {
                    return;
                }

                object materializedEnumValue;
                if (EnumValueMaterializationPolicy.TryMaterializeODataEnumValue(clientType, enumVal, out materializedEnumValue))
                {
                    containerProperty.Add(property.Name, materializedEnumValue);
                }

                return;
            }

            // Handle collection
            ODataCollectionValue collectionVal = value as ODataCollectionValue;

            if (collectionVal != null)
            {
                string collectionItemTypeName = CommonUtil.GetCollectionItemTypeName(collectionVal.TypeName, false);
                // Highly unlikely, but the method return null if the typeName argument does not meet certain expectations
                if (collectionItemTypeName == null)
                {
                    return;
                }

                Type collectionItemType;
                // ToNamedType will return true for primitive types
                if (!ClientConvert.ToNamedType(collectionItemTypeName, out collectionItemType))
                {
                    // Non-primitive collection
                    collectionItemType = ResolveClientTypeForDynamicProperty(collectionItemTypeName, instance);
                }

                if (collectionItemType == null)
                {
                    return;
                }

                object collectionInstance;
                if (this.CollectionValueMaterializationPolicy.TryMaterializeODataCollectionValue(collectionItemType, property, out collectionInstance))
                {
                    containerProperty.Add(property.Name, collectionInstance);
                }

                return;
            }
        }