/// <summary> /// Adds the given ResourceType to the cache. /// </summary> /// <param name="type">CLR type.</param> /// <param name="resourceType">ResourceType instance.</param> internal void AddResourceType(Type type, ResourceType resourceType) { var cacheItem = new ResourceTypeCacheItem(resourceType); this.typeCache.Add(type, cacheItem); }
/// <summary> /// Get the PropertyInfo for the given resource property /// </summary> /// <param name="resourceTypeCacheItem">Instance of ResourceTypeCacheItem containing the ResourceType instance.</param> /// <param name="resourceProperty">ResourceProperty instance.</param> /// <returns>PropertyInfo instance for the given ResourceProperty.</returns> protected ResourcePropertyCacheItem GetResourcePropertyCacheItem(ResourceTypeCacheItem resourceTypeCacheItem, ResourceProperty resourceProperty) { Debug.Assert(resourceTypeCacheItem.ResourceType.Properties.Contains(resourceProperty), "resourceTypeCacheItem.ResourceType.Properties.Contains(resourceProperty)"); var declaringResourceType = resourceTypeCacheItem.ResourceType.GetDeclaringTypeForProperty(resourceProperty); if (declaringResourceType != resourceTypeCacheItem.ResourceType) { resourceTypeCacheItem = this.ResolveNonPrimitiveTypeCacheItem(declaringResourceType.InstanceType); } return resourceTypeCacheItem.GetResourcePropertyCacheItem(resourceProperty); }
/// <summary>Sets the value of the property.</summary> /// <param name="instance">The object whose property needs to be set.</param> /// <param name="resourceTypeCacheItem">ResourceTypeCacheItem containing the ResourceType and its metadata representing the instance parameter.</param> /// <param name="propertyValue">new value for the property.</param> /// <param name="resourceProperty">metadata for the property to be set.</param> private void SetValue(object instance, ResourceTypeCacheItem resourceTypeCacheItem, object propertyValue, ResourceProperty resourceProperty) { Debug.Assert(instance != null, "instance != null"); Debug.Assert(resourceTypeCacheItem != null, "resourceTypeCacheItem != null"); Debug.Assert(resourceProperty != null, "resourceProperty != null"); MethodInfo setMethod = this.GetResourcePropertyCacheItem(resourceTypeCacheItem, resourceProperty).PropertyInfo.GetSetMethod(); if (setMethod == null) { throw ObjectContextServiceProvider.CreateBadRequestError(Strings.BadRequest_PropertyValueCannotBeSet(resourceProperty.Name)); } try { setMethod.Invoke(instance, new object[] { propertyValue }); } catch (TargetInvocationException exception) { ErrorHandler.HandleTargetInvocationException(exception); throw; } catch (ArgumentException exception) { throw ObjectContextServiceProvider.CreateBadRequestError(Strings.BadRequest_ErrorInSettingPropertyValue(resourceProperty.Name), exception); } }
/// <summary> /// Populates the member metadata for the given type /// </summary> /// <param name="resourceTypeCacheItem">Instance of ResourceTypeCacheItem containing the ResourceType and its metadata.</param> /// <param name="workspace">workspace containing the metadata information</param> /// <param name="metadataCacheItem">Instance of ProviderMetadataCacheItem.</param> /// <param name="primitiveResourceTypeMap">Map of primitive types to use when building member metadata.</param> internal static void PopulateMemberMetadata( ResourceTypeCacheItem resourceTypeCacheItem, IProviderMetadata workspace, ProviderMetadataCacheItem metadataCacheItem, PrimitiveResourceTypeMap primitiveResourceTypeMap) { Debug.Assert(resourceTypeCacheItem != null, "resourceTypeCacheItem != null"); Debug.Assert(workspace != null, "workspace != null"); var resourceType = resourceTypeCacheItem.ResourceType; // Find the type from the OSpace IProviderType edmType = workspace.GetProviderType(resourceType.FullName); foreach (IProviderMember member in edmType.Members) { ResourcePropertyKind kind = (ResourcePropertyKind)(-1); // ObjectContextServiceProvider fails with NullReferenceException when an entity property is not public. // If the property on the CLR type which is representing the EDM type has non-public properties but those properties are part of the // conceptual model, the server will try to load CLR metadata for these properties. // The Type.GetProperty(propertyName) method used BindingFlags.Instance | BindingFlags.Public by default if no binding flags are specified. // Since the property was not found with these binding flags, the GetProperty method returns null, which we didn't check for in v1 and v2 and threw an NRE. // We now check for null return values from this function and throw if we find that the model property declared on the CLR type is not public. PropertyInfo propertyInfo = resourceType.InstanceType.GetProperty(member.Name, BindingFlags.Instance | BindingFlags.Public); if (propertyInfo == null) { throw new DataServiceException((int)HttpStatusCode.InternalServerError, Strings.ObjectContext_PublicPropertyNotDefinedOnType(edmType.Name, member.Name)); } ResourceType propertyType = null; switch (member.EdmTypeKind) { case BuiltInTypeKind.PrimitiveType: #if !INTERNAL_DROP && !EFRTM Type propertyClrType = ObjectContextSpatialUtil.IsDbGeography(propertyInfo.PropertyType) ? typeof(Geography) : propertyInfo.PropertyType; #else Type propertyClrType = propertyInfo.PropertyType; #endif propertyType = primitiveResourceTypeMap.GetPrimitive(propertyClrType); if (propertyType == null) { throw new NotSupportedException(Strings.ObjectContext_PrimitiveTypeNotSupported(member.Name, edmType.Name, member.EdmTypeName)); } if (member.IsKey) { kind = ResourcePropertyKind.Key | ResourcePropertyKind.Primitive; } else { kind = ResourcePropertyKind.Primitive; } break; case BuiltInTypeKind.ComplexType: kind = ResourcePropertyKind.ComplexType; propertyType = metadataCacheItem.TryGetResourceType(propertyInfo.PropertyType); break; case BuiltInTypeKind.EntityType: kind = ResourcePropertyKind.ResourceReference; propertyType = metadataCacheItem.TryGetResourceType(propertyInfo.PropertyType); break; case BuiltInTypeKind.CollectionType: kind = ResourcePropertyKind.ResourceSetReference; Type collectionItemClrType = workspace.GetClrType(member.CollectionItemType); Debug.Assert(!WebUtil.IsPrimitiveType(collectionItemClrType), "We don't support collections of primitives, we shouldn't see one here"); propertyType = metadataCacheItem.TryGetResourceType(collectionItemClrType); break; default: throw new NotSupportedException(Strings.ObjectContext_PrimitiveTypeNotSupported(member.Name, edmType.Name, member.EdmTypeName)); } Debug.Assert(propertyType != null, "propertyType != null"); ResourceProperty resourceProperty = new ResourceProperty(propertyInfo.Name, kind, propertyType); SetMimeTypeForMappedMember(resourceProperty, member); resourceType.AddProperty(resourceProperty); #if !EF6Provider ObjectContextServiceProvider.PopulateFacets(resourceProperty, member.Facets, resourceProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.EntityType /*ignoreNullableAnnotation*/); ObjectContextServiceProvider.PopulateAnnotations(member.MetadataProperties, resourceProperty.AddCustomAnnotation); #endif resourceTypeCacheItem.AddResourcePropertyCacheItem(resourceProperty, new ObjectContextResourcePropertyCacheItem(propertyInfo, member)); } }
/// <summary> /// Adds the given ResourceType to the cache. /// </summary> /// <param name="type">CLR type.</param> /// <param name="resourceType">ResourceType instance.</param> internal void AddResourceType(Type type, ResourceType resourceType) { var cacheItem = new ResourceTypeCacheItem(resourceType); this.typeCache.Add(type, cacheItem); }