/// <summary> /// get property wrapper for a property name, might be method around open types for otherwise unknown properties /// </summary> /// <param name="propertyName">property name</param> /// <param name="undeclaredPropertyBehavior">UndeclaredPropertyBehavior</param> /// <returns>property wrapper</returns> /// <exception cref="InvalidOperationException">for unknown properties on closed types</exception> internal ClientPropertyAnnotation GetProperty(string propertyName, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { Debug.Assert(propertyName != null, "property name"); if (this.clientPropertyCache == null) { this.BuildPropertyCache(); } ClientPropertyAnnotation property; if (!this.clientPropertyCache.TryGetValue(propertyName, out property)) { string propertyClientName = ClientTypeUtil.GetClientPropertyName(this.ElementType, propertyName, undeclaredPropertyBehavior); if ((string.IsNullOrEmpty(propertyClientName) || !this.clientPropertyCache.TryGetValue(propertyClientName, out property)) && (undeclaredPropertyBehavior == UndeclaredPropertyBehavior.ThrowException)) { #if OPENSILVER throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientType_MissingProperty(this.ElementTypeName, propertyName)); #else throw Microsoft.OData.Client.Error.InvalidOperation(Microsoft.OData.Client.Strings.ClientType_MissingProperty(this.ElementTypeName, propertyName)); #endif } } return property; }
/// <summary> /// Set instance annotation for a property /// </summary> /// <param name="propertyName">Property name</param> /// <param name="instanceAnnotations">Intance annotations to be set</param> /// <param name="type">The type of the containing object</param> /// <param name="declaringInstance">The containing object instance</param> private void SetInstanceAnnotations(string propertyName, IDictionary <string, object> instanceAnnotations, Type type, object declaringInstance) { if (declaringInstance != null) { UndeclaredPropertyBehavior undeclaredPropertyBehavior = this.MaterializerContext.Context.UndeclaredPropertyBehavior; // Get the client property info ClientEdmModel edmModel = this.MaterializerContext.Model; ClientTypeAnnotation clientTypeAnnotation = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(type)); ClientPropertyAnnotation clientPropertyAnnotation = clientTypeAnnotation.GetProperty(propertyName, undeclaredPropertyBehavior); Tuple <object, MemberInfo> annotationKeyForProperty = new Tuple <object, MemberInfo>(declaringInstance, clientPropertyAnnotation.PropertyInfo); SetInstanceAnnotations(annotationKeyForProperty, instanceAnnotations); } }
/// <summary> /// Gets the clr name according to server defined name in the specified type. /// </summary> /// <param name="serverDefinedName">Name from server.</param> /// <param name="undeclaredPropertyBehavior">Flag to support untyped properties.</param> /// <returns>Client PropertyInfo, or null if the method is not found or throws exception if undeclaredPropertyBehavior is ThrowException.</returns> public PropertyInfo GetClientPropertyInfo(string serverDefinedName, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { PropertyInfo clientPropertyInfo = null; if (_propertyInfoDict == null) { _properties = GetAllProperties(); } if ((!_propertyInfoDict.TryGetValue(serverDefinedName, out clientPropertyInfo)) && undeclaredPropertyBehavior == UndeclaredPropertyBehavior.ThrowException) { throw c.Error.InvalidOperation(c.Strings.ClientType_MissingProperty(type.ToString(), serverDefinedName)); } return(clientPropertyInfo); }
/// <summary> /// Gets the clr name according to server defined name in the specified <paramref name="t"/>. /// </summary> /// <param name="t">The type used to get the client property name.</param> /// <param name="serverDefinedName">Name from server.</param> /// <param name="undeclaredPropertyBehavior">Flag to support untyped properties.</param> /// <returns>Client property name, or null if the property is not found.</returns> internal static string GetClientPropertyName(Type t, string serverDefinedName, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { PropertyInfo propertyInfo = GetClientPropertyInfo(t, serverDefinedName, undeclaredPropertyBehavior); return(propertyInfo == null ? serverDefinedName : propertyInfo.Name); }
/// <summary> /// Gets the clr name according to server defined name in the specified <paramref name="t"/>. /// </summary> /// <param name="t">The type used to get the client PropertyInfo.</param> /// <param name="serverDefinedName">Name from server.</param> /// <param name="undeclaredPropertyBehavior">Flag to support untyped properties.</param> /// <returns>Client PropertyInfo, or null if the method is not found.</returns> internal static PropertyInfo GetClientPropertyInfo(Type t, string serverDefinedName, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { PropertyInfo propertyInfo = t.GetProperty(serverDefinedName); if (propertyInfo == null) { propertyInfo = t.GetProperties().Where( m => { OriginalNameAttribute originalNameAttribute = (OriginalNameAttribute)m.GetCustomAttributes(typeof(OriginalNameAttribute), false).SingleOrDefault(); return(originalNameAttribute != null && originalNameAttribute.OriginalName == serverDefinedName); }).SingleOrDefault(); } if (propertyInfo == null && (undeclaredPropertyBehavior == UndeclaredPropertyBehavior.ThrowException)) { throw c.Error.InvalidOperation(c.Strings.ClientType_MissingProperty(t.ToString(), serverDefinedName)); } return(propertyInfo); }
/// <summary> /// Materializes the primitive data values in the given list of <paramref name="values"/>. /// </summary> /// <param name="actualType">Actual type for properties being materialized.</param> /// <param name="values">List of values to materialize.</param> /// <param name="undeclaredPropertyBehavior"> /// Whether properties missing from the client types should be supported or throw exception. /// </param> /// <remarks> /// Values are materialized in-place with each <see cref="ODataProperty"/> /// instance. /// </remarks> internal void MaterializeDataValues(ClientTypeAnnotation actualType, IEnumerable <ODataProperty> values, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { Debug.Assert(actualType != null, "actualType != null"); Debug.Assert(values != null, "values != null"); foreach (var odataProperty in values) { if (odataProperty.Value is ODataStreamReferenceValue) { continue; } string propertyName = odataProperty.Name; var property = actualType.GetProperty(propertyName, undeclaredPropertyBehavior); // may throw if (property == null) { continue; } // we should throw if the property type on the client does not match with the property type in the server // This is a breaking change from V1/V2 where we allowed materialization of entities into non-entities and vice versa if (ClientTypeUtil.TypeOrElementTypeIsEntity(property.PropertyType)) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidEntityType(property.EntityCollectionItemType ?? property.PropertyType)); } if (property.IsKnownType) { // Note: MaterializeDataValue materializes only properties of primitive types. Materialization specific // to complex types and collections is done later. this.MaterializePrimitiveDataValue(property.NullablePropertyType, odataProperty); } } }
/// <summary> /// Gets the clr name according to server defined name in the specified <paramref name="t"/>. /// </summary> /// <param name="t">The type used to get the client PropertyInfo.</param> /// <param name="serverDefinedName">Name from server.</param> /// <param name="undeclaredPropertyBehavior">Flag to support untyped properties.</param> /// <returns>Client PropertyInfo, or null if the method is not found or throws exception if undeclaredPropertyBehavior is ThrowException.</returns> internal static PropertyInfo GetClientPropertyInfo(Type t, string serverDefinedName, UndeclaredPropertyBehavior undeclaredPropertyBehavior) { ODataTypeInfo typeInfo = GetODataTypeInfo(t); return(typeInfo.GetClientPropertyInfo(serverDefinedName, undeclaredPropertyBehavior)); }