/// <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; } }