public EntityPropertyMappingInfo(EntityPropertyMappingAttribute attribute, Type definingType, ClientTypeAnnotation actualPropertyType) { this.attribute = attribute; this.definingType = definingType; this.actualPropertyType = actualPropertyType; this.propertyValuePath = attribute.SourcePath.Split(new char[] { '/' }); this.isSyndicationMapping = this.attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty; }
/// <summary> /// Creates instance of EntityPropertyMappingInfo class. /// </summary> /// <param name="attribute">The <see cref="EntityPropertyMappingAttribute"/> corresponding to this object</param> /// <param name="definingType">Type the <see cref="EntityPropertyMappingAttribute"/> was defined on.</param> /// <param name="actualPropertyType">ClientType whose property is to be read.</param> public EntityPropertyMappingInfo(EntityPropertyMappingAttribute attribute, Type definingType, ClientTypeAnnotation actualPropertyType) { #endif Debug.Assert(attribute != null, "attribute != null"); Debug.Assert(definingType != null, "definingType != null"); Debug.Assert(actualPropertyType != null, "actualPropertyType != null"); this.attribute = attribute; this.definingType = definingType; this.actualPropertyType = actualPropertyType; Debug.Assert(!string.IsNullOrEmpty(attribute.SourcePath), "Invalid source path"); this.propertyValuePath = attribute.SourcePath.Split('/'); // Infer the mapping type from the attribute this.isSyndicationMapping = this.attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty; }
/// <summary>Validates the specified segment and all its subsegments.</summary> /// <param name="pathSegment">The path segment to validate.</param> /// <param name="resourceType">The resource type of the property represented by this segment (null for open properties).</param> /// <param name="declaredPropertiesLookup">The dictionary to lookup and add declaredProperties associated with resourceTypes.</param> private static void Validate(EpmSourcePathSegment pathSegment, ClientTypeOrResourceType_Alias resourceType, Dictionary <ResourceType, IEnumerable <ResourceProperty> > declaredPropertiesLookup) #endif { Debug.Assert(pathSegment != null, "pathSegment != null"); foreach (EpmSourcePathSegment subSegment in pathSegment.SubProperties) { #if ASTORIA_CLIENT ClientTypeOrResourceType_Alias subSegmentResourceType = GetPropertyType(resourceType, subSegment.PropertyName); // sometimes the previous call returns null, WHY do we even bother // to continue on after we can't find a resourceType? Validate(subSegment, subSegmentResourceType); #else ClientTypeOrResourceType_Alias subSegmentResourceType = GetPropertyType(resourceType, subSegment.PropertyName, declaredPropertiesLookup); // sometimes the previous call returns null, WHY do we even bother // to continue on after we can't find a resourceType? Validate(subSegment, subSegmentResourceType, declaredPropertiesLookup); #endif } }
private static ClientTypeAnnotation GetPropertyType(ClientTypeAnnotation clientType, string propertyName) { ClientPropertyAnnotation property = clientType.GetProperty(propertyName, true); if (property == null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_InaccessiblePropertyOnType(propertyName, clientType.ElementTypeName)); } if (property.IsStreamLinkProperty) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_NamedStreamCannotBeMapped(propertyName, clientType.ElementTypeName)); } if (property.IsSpatialType) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_SpatialTypeCannotBeMapped(propertyName, clientType.ElementTypeName)); } if (property.IsPrimitiveOrComplexCollection) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.EpmSourceTree_CollectionPropertyCannotBeMapped(propertyName, clientType.ElementTypeName)); } ClientEdmModel model = ClientEdmModel.GetModel(clientType.MaxProtocolVersion); IEdmType orCreateEdmType = model.GetOrCreateEdmType(property.PropertyType); return model.GetClientTypeAnnotation(orCreateEdmType); }
/// <summary> /// Sets the single instance of <see cref="ClientTypeAnnotation"/> on the given instance of <paramref name="edmType"/>. /// </summary> /// <param name="model">The model the <paramref name="edmType"/> belongs to.</param> /// <param name="edmType">IEdmType instance to set the annotation on.</param> /// <param name="annotation">The annotation to set</param> internal static void SetClientTypeAnnotation(this IEdmModel model, IEdmType edmType, ClientTypeAnnotation annotation) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmType != null, "edmType != null"); Debug.Assert(annotation != null, "annotation != null"); model.SetAnnotationValue <ClientTypeAnnotation>(edmType, annotation); }
/// <summary> /// Builds the EntityPropertyMappingInfo corresponding to an EntityPropertyMappingAttribute, also builds the delegate to /// be invoked in order to retrieve the property provided in the <paramref name="epmAttr"/> /// </summary> /// <param name="epmAttr">Source EntityPropertyMappingAttribute</param> /// <param name="definingType">ResourceType on which to look for the property</param> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> private static void BuildEpmInfo(EntityPropertyMappingAttribute epmAttr, Type definingType, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { sourceTree.Add(new System.Data.Services.Client.Serializers.EntityPropertyMappingInfo(epmAttr, definingType, clientTypeAnnotation)); }
private static void BuildEpmInfo(Type type, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { if (clientTypeAnnotation.IsEntityType) { Func<EntityPropertyMappingAttribute, bool> predicate = null; Type baseType = type.BaseType; ClientTypeAnnotation annotation = null; ClientEdmModel model = ClientEdmModel.GetModel(clientTypeAnnotation.MaxProtocolVersion); ODataEntityPropertyMappingCollection mappings = null; if ((baseType != null) && (baseType != typeof(object))) { if (((EdmStructuredType) clientTypeAnnotation.EdmType).BaseType == null) { BuildEpmInfo(baseType, clientTypeAnnotation, sourceTree); mappings = model.GetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); } else { annotation = model.GetClientTypeAnnotation(baseType); BuildEpmInfo(baseType, annotation, sourceTree); } } foreach (EntityPropertyMappingAttribute attribute in type.GetCustomAttributes(typeof(EntityPropertyMappingAttribute), false)) { BuildEpmInfo(attribute, type, clientTypeAnnotation, sourceTree); if (mappings == null) { mappings = new ODataEntityPropertyMappingCollection(); } mappings.Add(attribute); } if (mappings != null) { ODataEntityPropertyMappingCollection annotationValue = model.GetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType); if (annotationValue != null) { if (predicate == null) { predicate = oldM => !mappings.Any<EntityPropertyMappingAttribute>(newM => (oldM.SourcePath == newM.SourcePath)); } foreach (EntityPropertyMappingAttribute attribute2 in annotationValue.Where<EntityPropertyMappingAttribute>(predicate).ToList<EntityPropertyMappingAttribute>()) { mappings.Add(attribute2); } } model.SetAnnotationValue<ODataEntityPropertyMappingCollection>(clientTypeAnnotation.EdmType, mappings); } } }
internal EpmLazyLoader(ClientTypeAnnotation clientTypeAnnotation) { this.clientTypeAnnotation = clientTypeAnnotation; }
internal IEnumerable<ODataProperty> PopulateProperties(ClientTypeAnnotation type, object resource, List<object> visitedComplexTypeObjects) { List<ODataProperty> list = new List<ODataProperty>(); foreach (ClientPropertyAnnotation annotation in from p in type.Properties() orderby p.PropertyName select p) { if (((!annotation.IsDictionary && (annotation != type.MediaDataMember)) && !annotation.IsStreamLinkProperty) && ((type.MediaDataMember == null) || (type.MediaDataMember.MimeTypeProperty != annotation))) { object propertyValue = annotation.GetValue(resource); if (annotation.IsKnownType) { ODataProperty item = new ODataProperty { Name = annotation.EdmProperty.Name, Value = GetPrimitiveValue(propertyValue, annotation.PropertyType) }; list.Add(item); } else if (annotation.IsPrimitiveOrComplexCollection) { ODataProperty property2 = new ODataProperty { Name = annotation.EdmProperty.Name, Value = this.CreateODataCollectionPropertyValue(annotation, propertyValue, visitedComplexTypeObjects) }; list.Add(property2); } else if (!annotation.IsEntityCollection && !ClientTypeUtil.TypeIsEntity(annotation.PropertyType, this.requestInfo.MaxProtocolVersion)) { ODataProperty property3 = new ODataProperty { Name = annotation.EdmProperty.Name, Value = this.CreateODataComplexPropertyValue(annotation, propertyValue, visitedComplexTypeObjects) }; list.Add(property3); } } } return list; }
internal static void SetClientTypeAnnotation(this IEdmType edmType, ClientTypeAnnotation annotation) { ClientEdmModel.GetModel(annotation.MaxProtocolVersion).SetAnnotationValue<ClientTypeAnnotation>(edmType, annotation); }
private ClientTypeAnnotation GetOrCreateClientTypeAnnotation(IEdmType edmType, Type type) { string key = type.ToString(); if ((edmType.TypeKind == EdmTypeKind.Complex) || (edmType.TypeKind == EdmTypeKind.Entity)) { lock (this.typeNameToClientTypeAnnotationCache) { ClientTypeAnnotation annotation; if (this.typeNameToClientTypeAnnotationCache.TryGetValue(key, out annotation) && (annotation.ElementType != type)) { key = type.AssemblyQualifiedName; if (this.typeNameToClientTypeAnnotationCache.TryGetValue(key, out annotation) && (annotation.ElementType != type)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.ClientType_MultipleTypesWithSameName(key)); } } if (annotation == null) { annotation = new ClientTypeAnnotation(edmType, type, key, this.protocolVersion); this.typeNameToClientTypeAnnotationCache.Add(key, annotation); } return annotation; } } return new ClientTypeAnnotation(edmType, type, key, this.protocolVersion); }
internal string GetServerTypeName(ClientTypeAnnotation clientTypeAnnotation) { return this.ResolveNameFromType(clientTypeAnnotation.ElementType); }
private static void Validate(EpmSourcePathSegment pathSegment, ClientTypeAnnotation resourceType) { foreach (EpmSourcePathSegment segment in pathSegment.SubProperties) { ClientTypeAnnotation propertyType = GetPropertyType(resourceType, segment.PropertyName); Validate(segment, propertyType); } }
internal void Validate(ClientTypeAnnotation resourceType) { Validate(this.Root, resourceType); }
private static Version DetermineRequestVersion(ClientTypeAnnotation clientType, EntityStates state) { if (state == EntityStates.Deleted) { return Util.DataServiceVersion1; } Version version = Util.DataServiceVersion1; WebUtil.RaiseVersion(ref version, clientType.GetMetadataVersion()); WebUtil.RaiseVersion(ref version, clientType.EpmMinimumDataServiceProtocolVersion.ToVersion()); return version; }
/// <summary>Validates the source tree.</summary> /// <param name="resourceType">The resource type for which the validation is performed.</param> internal void Validate(ClientTypeOrResourceType_Alias resourceType) { Validate(this.Root, resourceType); }
/// <summary>Validates the specified segment and all its subsegments.</summary> /// <param name="pathSegment">The path segment to validate.</param> /// <param name="resourceType">The resource type of the property represented by this segment (null for open properties).</param> private static void Validate(EpmSourcePathSegment pathSegment, ClientTypeOrResourceType_Alias resourceType)
protected static void ApplyDataValues(ClientTypeAnnotation type, IEnumerable<ODataProperty> properties, bool ignoreMissingProperties, System.Data.Services.Client.ResponseInfo responseInfo, object instance) { foreach (ODataProperty property in properties) { ApplyDataValue(type, property, ignoreMissingProperties, responseInfo, instance); } }
internal void Add(EntityPropertyMappingInfo epmInfo, IEnumerable <ResourceProperty> declaredProperties) { Dictionary <ResourceType, IEnumerable <ResourceProperty> > declaredPropertiesLookup = new Dictionary <ResourceType, IEnumerable <ResourceProperty> >(EqualityComparer <ResourceType> .Default); declaredPropertiesLookup.Add(epmInfo.ActualPropertyType, declaredProperties); #endif EpmSourcePathSegment currentSourceSegment = this.Root; EpmSourcePathSegment foundSourceSegment = null; ClientTypeOrResourceType_Alias currentType = epmInfo.ActualPropertyType; Debug.Assert(epmInfo.PropertyValuePath != null && epmInfo.PropertyValuePath.Length > 0, "Must have been validated during EntityPropertyMappingAttribute construction"); for (int sourcePropertyIndex = 0; sourcePropertyIndex < epmInfo.PropertyValuePath.Length; sourcePropertyIndex++) { string propertyName = epmInfo.PropertyValuePath[sourcePropertyIndex]; if (propertyName.Length == 0) { throw new InvalidOperationException(c.Strings.EpmSourceTree_InvalidSourcePath(epmInfo.DefiningType.Name, epmInfo.Attribute.SourcePath)); } #if ASTORIA_CLIENT currentType = GetPropertyType(currentType, propertyName); #else currentType = GetPropertyType(currentType, propertyName, declaredPropertiesLookup); #endif foundSourceSegment = currentSourceSegment.SubProperties.SingleOrDefault(e => e.PropertyName == propertyName); if (foundSourceSegment != null) { currentSourceSegment = foundSourceSegment; } else { EpmSourcePathSegment newSourceSegment = new EpmSourcePathSegment(propertyName); currentSourceSegment.SubProperties.Add(newSourceSegment); currentSourceSegment = newSourceSegment; } } // The last segment is the one being mapped from by the user specified attribute. // It must be a primitive type - we don't allow mappings of anything else than primitive properties directly. // Note that we can only verify this for non-open properties, for open properties we must assume it's a primitive type // and we will make this check later during serialization again when we actually have the value of the property. if (currentType != null) { #if ASTORIA_CLIENT if (!PrimitiveType.IsKnownNullableType(currentType.ElementType)) #else if (currentType.ResourceTypeKind != ResourceTypeKind.Primitive) #endif { throw new InvalidOperationException(c.Strings.EpmSourceTree_EndsWithNonPrimitiveType(currentSourceSegment.PropertyName)); } } // Note that once we're here the EpmInfo we have is never the collection property itself, it's always either a non-collection property // or collection item property. Debug.Assert(foundSourceSegment == null || foundSourceSegment.EpmInfo != null, "Can't have a leaf node in the tree without EpmInfo."); // Two EpmAttributes with same PropertyName in the same ResourceType, this could be a result of inheritance if (foundSourceSegment != null) { Debug.Assert(Object.ReferenceEquals(foundSourceSegment, currentSourceSegment), "currentSourceSegment variable should have been updated already to foundSourceSegment"); // Check for duplicates on the same entity type Debug.Assert(foundSourceSegment.SubProperties.Count == 0, "If non-leaf, it means we allowed complex type to be a leaf node"); if (foundSourceSegment.EpmInfo.DefiningTypesAreEqual(epmInfo)) { throw new InvalidOperationException(c.Strings.EpmSourceTree_DuplicateEpmAttrsWithSameSourceName(epmInfo.Attribute.SourcePath, epmInfo.DefiningType.Name)); } // In case of inheritance, we need to remove the node from target tree which was mapped to base type property this.epmTargetTree.Remove(foundSourceSegment.EpmInfo); } currentSourceSegment.EpmInfo = epmInfo; this.epmTargetTree.Add(epmInfo); }
protected static void MaterializeDataValues(ClientTypeAnnotation actualType, IEnumerable<ODataProperty> values, bool ignoreMissingProperties) { foreach (ODataProperty property in values) { if (!(property.Value is ODataStreamReferenceValue)) { string name = property.Name; ClientPropertyAnnotation annotation = actualType.GetProperty(name, ignoreMissingProperties); if (annotation != null) { if (ClientTypeUtil.TypeOrElementTypeIsEntity(annotation.PropertyType)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidEntityType(annotation.EntityCollectionItemType ?? annotation.PropertyType)); } if (annotation.IsKnownType) { MaterializePrimitiveDataValue(annotation.NullablePropertyType, property); } } } } }
internal static void SetClientTypeAnnotation(this IEdmType edmType, ClientTypeAnnotation annotation) { ClientEdmModel.GetModel(annotation.MaxProtocolVersion).SetAnnotationValue <ClientTypeAnnotation>(edmType, annotation); }
protected static void ApplyDataValue(ClientTypeAnnotation type, ODataProperty property, bool ignoreMissingProperties, System.Data.Services.Client.ResponseInfo responseInfo, object instance) { ClientPropertyAnnotation annotation = type.GetProperty(property.Name, ignoreMissingProperties); if (annotation != null) { if (annotation.IsPrimitiveOrComplexCollection) { if (property.Value == null) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Collection_NullCollectionNotSupported(property.Name)); } if (property.Value is string) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MixedTextWithComment); } if (property.Value is ODataComplexValue) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidCollectionItem(property.Name)); } object obj2 = annotation.GetValue(instance); if (obj2 == null) { obj2 = CreateCollectionInstance(property, annotation.PropertyType, responseInfo); annotation.SetValue(instance, obj2, property.Name, false); } else { annotation.ClearBackingICollectionInstance(obj2); } ApplyCollectionDataValues(property, ignoreMissingProperties, responseInfo, obj2, annotation.PrimitiveOrComplexCollectionItemType, new Action<object, object>(annotation.AddValueToBackingICollectionInstance)); } else { object obj3 = property.Value; ODataComplexValue value2 = obj3 as ODataComplexValue; if ((obj3 != null) && (value2 != null)) { if (!annotation.EdmProperty.Type.IsComplex()) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_ExpectingSimpleValue); } bool flag = false; ClientEdmModel model = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(annotation.PropertyType)); object obj4 = annotation.GetValue(instance); if (obj4 == null) { obj4 = clientTypeAnnotation.CreateInstance(); flag = true; } MaterializeDataValues(clientTypeAnnotation, value2.Properties, ignoreMissingProperties); ApplyDataValues(clientTypeAnnotation, value2.Properties, ignoreMissingProperties, responseInfo, obj4); if (flag) { annotation.SetValue(instance, obj4, property.Name, true); } } else { MaterializePrimitiveDataValue(annotation.NullablePropertyType, property); annotation.SetValue(instance, property.GetMaterializedValue(), property.Name, true); } } } }
private static void BuildEpmInfo(ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { BuildEpmInfo(clientTypeAnnotation.ElementType, clientTypeAnnotation, sourceTree); }
/// <summary> /// Initializes a new instance of the <see cref="EpmLazyLoader"/> class. /// </summary> /// <param name="clientTypeAnnotation">The client type annotation.</param> internal EpmLazyLoader(ClientTypeAnnotation clientTypeAnnotation) { this.clientTypeAnnotation = clientTypeAnnotation; }
private static void BuildEpmInfo(EntityPropertyMappingAttribute epmAttr, Type definingType, ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { sourceTree.Add(new System.Data.Services.Client.Serializers.EntityPropertyMappingInfo(epmAttr, definingType, clientTypeAnnotation)); }
/// <summary> /// By going over EntityPropertyMappingInfoAttribute(s) defined on the ElementType /// builds the corresponding EntityPropertyMappingInfo /// </summary> /// <param name="clientTypeAnnotation">The ClientTypeAnnotation to refer to</param> /// <param name="sourceTree">The source tree to populate.</param> /// <remarks>This method should be called after all properties are set on the edm type.</remarks> private static void BuildEpmInfo(ClientTypeAnnotation clientTypeAnnotation, System.Data.Services.Client.Serializers.EpmSourceTree sourceTree) { BuildEpmInfo(clientTypeAnnotation.ElementType, clientTypeAnnotation, sourceTree); }